gpt4 book ai didi

c++ - 使用参数包扩展生成 Constexpr

转载 作者:行者123 更新时间:2023-11-30 01:05:21 25 4
gpt4 key购买 nike

我有以下代码:

#include <vector>
#include <array>

using std::vector;

enum EventType {
EventType_Collision,
EventType_Accelerate,
EventType_Glide
};

template<class T, EventType... events>
class A {
private:
static unsigned short CalcBitMask(EventType e) { return 1 << e; }
static constexpr unsigned short listeners = 0 | CalcBitMask(events)...;
protected:
//static constexpr int InternalGetType() { return 0; }
public:
static constexpr int GetType() { return T::InternalGetType(); }
static constexpr int GetListeners() { return listeners; }
};

class B : public A<B, EventType_Accelerate, EventType_Collision > {
friend class A<B, EventType_Accelerate, EventType_Collision>;
protected:
static constexpr int InternalGetType() { return 1; }
};

我正在尝试根据传递到模板中的 EvenType 参数创建位掩码。不幸的是,传递的 EvenTypes 数量是可变的。但是由于我们在编译时拥有所有参数,因此在编译时根据给定参数计算一个值似乎更有可能作为 constexpr。另一方面,我得到的是:

表达式未计算为常量

对于监听器变量。有任何想法吗?提前致谢。

附言在一个完全不相关的说明上,如果有人知道我如何可以消除冗长的友元类声明而不影响性能并隐藏 InternalGetType() 函数,我会很高兴并且非常感谢听到它。

编辑

为了回应最近的建议,我仅限于使用 C++14

编辑

这就是我使用递归模板调用使它工作的方法crtp.h

#pragma once
#include <vector>
#include <array>

using std::vector;

enum EventType {
EventType_Collision,
EventType_Accelerate,
EventType_Glide
};

template<class T, EventType... events>
class A {
private:
template <EventType Last>
static constexpr unsigned short BitCalc() {
return 1 << Last;
}

template <EventType First, EventType Second, EventType ...Rest>
static constexpr unsigned short BitCalc() {
return BitCalc<First>() | BitCalc<Second, Rest...>();
}
static constexpr unsigned short listeners = BitCalc<events...>();
protected:
//static constexpr int InternalGetType() { return 0; }
public:
static constexpr int GetType() { return T::InternalGetType(); }
static constexpr int GetListeners() { return listeners; }
};

class B : public A<B, EventType_Accelerate, EventType_Collision > {
friend class A<B, EventType_Accelerate, EventType_Collision>;
protected:
static constexpr int InternalGetType() { return 1; }
};

主要.cpp

#include "ctrp.h"
#include <iostream>
#include <vector>
#include<bitset>

using std::cout;
using std::vector;
using std::getchar;
using std::endl;

int main() {
B b;
cout << "Bitmask: " << std::bitset<16>(b.GetListeners());
getchar();
return 0;
}

最佳答案

如果您可以使用 C++17,折叠表达式(请参阅 HolyBlackCat 的回答)是(恕我直言)解决问题的一种非常简单而优雅的方法。

如果你不能使用 C++17...我能想到的最好的方法是为 class A 开发一个 static constexpr 方法;如下内容

constexpr static unsigned short calcCombinedBitMask ()
{
using unused = unsigned short [];

unsigned short ret { 0 };

(void)unused { 0, ret |= CalcBitMask(events)... };

return ret;
}

所以你可以这样初始化listener

static constexpr unsigned short listeners = calcCombinedBitMask();

对于 C++11,我建议的解决方案与您的解决方案略有不同

static constexpr unsigned short CalcBitMask (EventType e)
{ return 1 << e; }

static constexpr unsigned short BitCalc()
{ return 0; }

template <EventType First, EventType ... Rest>
static constexpr unsigned short BitCalc()
{ return CalcBitMask(First) | BitCalc<Rest...>(); }

关于c++ - 使用参数包扩展生成 Constexpr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48632867/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com