簡體   English   中英

使用參數包擴展生成Constexpr

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM