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++14constepr
函数开始才能如此复杂。您是在编译C++11还是C++14?如果您需要C++11解决方案,我可以尝试创建一个递归版本的calcCombinedBitMask()
。我正在编译C++14,我找到了一种使用递归模板函数使其工作的方法,但老实说,我对它们仍然有点不确定,所以我很感激(如果不是太麻烦的话),如果你能看看我刚才添加到问题中的代码,看看a)我是否正确,和/或b)是否有更好/更优雅的方法来实现它,那就可以了!我发誓你可以用模板来完成这些事情,这太神奇了,谢谢你。只是为了确保我从性能角度正确地思考问题,没有区别调用calcBitMask()之间的差异
每次都不要使用监听器
变量,因为函数将预先计算并内联,对吗?@Ryoku-是的,变量模板非常好。对于性能问题…我不是一个真正的专家,但是…考虑到监听器
是一个静态constepr
成员;它也是(相当好的)当然,预先计算的编译时间。calbBitMask()
和calccomniedbitmask()
都是方法。因此它们可以在编译时使用(例如,将conexpr
变量初始化为listener
)或运行时使用(例如,将新值分配给非常量变量)因此,如果使用listener
则使用编译时计算值;如果使用calcBitMask()
,您可以要求它的微积分运行时。好吧,我刚刚遇到一个错误。我终于能够在我的系统中构建代码,它出现了错误“ret”:在“constexpr”函数体中不允许声明,我想这是告诉我不能在co中使用变量的一种方式