我有以下代码:
#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
似乎更有可能。另一方面,我得到的是:
expression did not evaluate to a constant
对于listeners变量。有任何想法吗?提前谢谢。
P.S。在一个完全不相关的说明中,如果有人知道我如何能够消除冗长的朋友类声明而不会影响性能并保持隐藏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; }
};
的main.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;
}
答案 0 :(得分:3)
如果你可以使用C ++ 17,折叠表达式(参见HolyBlackCat&#39;答案)是(恕我直言)一种非常简单和优雅的方式来解决问题。
如果你不能使用C ++ 17 ......我能想象的最好的是为static constexpr
开发class A
方法;以下内容
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...>(); }
答案 1 :(得分:2)
要求fold expressions。请注意,它们是一个相对较新的功能,在C ++ 17中添加。
static constexpr unsigned short listeners = (CalcBitMask(events) | ...);
您也忘记了CalcBitMask()
constexpr
。