![](/img/trans.png)
[英]Syntax of '…' with Parameter Pack Expansion using std::forward
[英]Using Parameter Pack Expansion to Generate a 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 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變量。 有任何想法嗎? 提前致謝。
PS在一個完全不相關的注釋上,如果有人有任何想法,我可以消除冗長的朋友類聲明而又不影響性能,並且不隱藏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;
}
如果可以使用C ++ 17,則折疊表達式(請參閱HolyBlackCat的答案)是(IMHO)解決問題的一種真正簡單而優雅的方法。
如果您不能使用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 ++ 17中新增的相對較新的功能。
static constexpr unsigned short listeners = (CalcBitMask(events) | ...);
您也忘記了讓CalcBitMask()
constexpr
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.