C++ 使用参数包扩展生成Constexpr

C++ 使用参数包扩展生成Constexpr,c++,c++14,variadic-templates,template-meta-programming,constexpr,C++,C++14,Variadic Templates,Template Meta Programming,Constexpr,我有以下代码: #include <vector> #include <array> using std::vector; enum EventType { EventType_Collision, EventType_Accelerate, EventType_Glide }; template<class T, EventType... events> class A { private: static unsigne

我有以下代码:

#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; }
};
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;
}
#包括“ctrp.h”
#包括
#包括
#包括
使用std::cout;
使用std::vector;
使用std::getchar;
使用std::endl;
int main(){
B B;
请注意,它们是C++17中添加的一个相对较新的特性

static constexpr unsigned short listeners = (CalcBitMask(events) | ...);
另外,您忘了制作要求的
CalcBitMask()
constepr

。请注意,它们是C++17中添加的一个相对较新的功能

static constexpr unsigned short listeners = (CalcBitMask(events) | ...);

此外,您还忘了使用
CalcBitMask()
constepr

如果您可以使用C++17,折叠表达式(请参见HolyBlackCat的答案)是一种非常简单和优雅的解决问题的方法

如果你不能使用C++17,我能想象的最好的方法就是为
类a
开发一个
静态constexpr
方法,如下所示

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

   unsigned short  ret { 0 };

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

   return ret;
 }
因此,您可以用这种方式初始化
侦听器

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...>(); }
static constexpr unsigned short CalcBitMask(事件类型e)

{return 1如果可以使用C++17,折叠表达式(见HolyBlackCat的答案)是(IMHO)一种非常简单而优雅的解决问题的方法

如果你不能使用C++17,我能想象的最好的方法就是为
类a
开发一个
静态constexpr
方法,如下所示

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

   unsigned short  ret { 0 };

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

   return ret;
 }
因此,您可以用这种方式初始化
侦听器

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...>(); }
static constexpr unsigned short CalcBitMask(事件类型e)

{return 1哇谢谢,我很难为情地说我花了多长时间才弄明白……好吧,现在当我运行程序时,优化编译器停止工作,最终它吐出了一个
语法错误“…”
,用于侦听器的初始化。有没有想过为什么会这样做?Aww man@max66你说得对。好的不幸的是,我的方法是去,但我只限于使用C++ 14。还有其他的想法吗?作为一个侧面的注释:模板的添加方式对C++的好处是什么?17@Ryoku那么max66的答案应该会有帮助。哇,谢谢你,我很难说我花了多长时间才弄明白……好吧,现在当我运行程序时,优化公司mpiler停止工作,最终它为侦听器的初始化抛出了一个
语法错误“…”
。有没有想过为什么会这样做?Aww man@max66你说得很对。好吧,这很好,但很遗憾,我仅限于使用C++14。还有其他想法吗?顺便说一句,这是一个很好的补充模板的方式去C++17@Ryoku那么max66的答案应该会有帮助。太好了,那就可以了!我发誓你可以用模板做的事情,真是太棒了,谢谢你。为了确保我从性能角度正确思考问题,调用
calcBitMask()没有什么区别
每次都不要使用
监听器
变量,因为函数将预先计算并内联,对吗?@Ryoku-是的,变量模板非常好。对于性能问题…我不是一个真正的专家,但是…考虑到
监听器
是一个
静态constepr
成员;它也是(相当好的)当然,预先计算的编译时间。
calbBitMask()
calccomniedbitmask()
都是方法。因此它们可以在编译时使用(例如,将
conexpr
变量初始化为
listener
)或运行时使用(例如,将新值分配给非常量变量)因此,如果使用
listener
则使用编译时计算值;如果使用
calcBitMask()
,你可以要求它的微积分运行时。好吧,我只是遇到了一个错误。我终于能够在我的系统中构建代码,它出现了错误
“ret”:在“constexpr”函数体中不允许声明,我想这是告诉我不能在constexpr中使用变量的一种方式。这看起来很奇怪,因为它的hin其范围。@Ryoku-对不起:我忘了只有从C++14
constepr
函数开始才能如此复杂。您是在编译C++11还是C++14?如果您需要C++11解决方案,我可以尝试创建一个递归版本的
calcCombinedBitMask()
。我正在编译C++14,我找到了一种使用递归模板函数使其工作的方法,但老实说,我对它们仍然有点不确定,所以我很感激(如果不是太麻烦的话),如果你能看看我刚才添加到问题中的代码,看看a)我是否正确,和/或b)是否有更好/更优雅的方法来实现它,那就可以了!我发誓你可以用模板来完成这些事情,这太神奇了,谢谢你。只是为了确保我从性能角度正确地思考问题,没有区别调用
calcBitMask()之间的差异
每次都不要使用
监听器
变量,因为函数将预先计算并内联,对吗?@Ryoku-是的,变量模板非常好。对于性能问题…我不是一个真正的专家,但是…考虑到
监听器
是一个
静态constepr
成员;它也是(相当好的)当然,预先计算的编译时间。
calbBitMask()
calccomniedbitmask()
都是方法。因此它们可以在编译时使用(例如,将
conexpr
变量初始化为
listener
)或运行时使用(例如,将新值分配给非常量变量)因此,如果使用
listener
则使用编译时计算值;如果使用
calcBitMask()
,您可以要求它的微积分运行时。好吧,我刚刚遇到一个错误。我终于能够在我的系统中构建代码,它出现了错误
“ret”:在“constexpr”函数体中不允许声明,我想这是告诉我不能在co中使用变量的一种方式