[英]C++ metaprogramming
我有以下問題:
假設我有一些基本的計數器class Counter
。 並假設我們還有一些可以計數的類集。 讓我們將其中一些命名為class CountedA
class CountedB
和class CountedB
。
現在,每個可以計數的類(例如CountedA
和CountedB
)都具有以下靜態聲明的部分: 一個enum
和一個int
部分,其作用類似於已計數數據的一部分 。
例如,它的聲明可能如下所示:
enum CountedType { A, B };
template <CountedType Type, int N>
class Counted { };
// Now we can declare 'CountedA' and 'CountedB'
typedef Counted<A, 25> CountedA;
typedef Counted<B, 7> CountedB;
現在,櫃台的聲明:
// C++0x variadic or simply bunch of 'typename XX' definitions for C++03
template <typename T0, typename T1, typename ...>
class Counter
{
// I don't know how to implement this
// for now!
int GetTotalN() { ... }
// Retrieve the corresponding type
// so that GetTypeAt<0> returns
// enum from 'T0'
template <int Pos>
CountedType GetTypeAt() { ... }
};
我希望能夠編寫如下內容:
class RealCounter : public Counter<CountedA, CountedB> { };
並通過以下方式使用它:
RealCounter counter;
int n = counter.GetTotalN();
CountedType type = counter.GetTypeAt<0>();
現在,我很確定可以做到這一點。 但是實現它的最佳方法是什么? (不要問我為什么我需要這么瘋狂的事情:)
boost::mpl
在這種情況下是否提供了某些東西?
謝謝。
小更新:
在此特定示例中, GetTotalN()
應該返回25 + 7
。
例如,如果我們添加typedef Counted<C, 2> CountedC
,則結果為
RealCounter : public Counter<CountedA, CountedB, CountedC>
應該變成25 + 7 + 2
。
這是有效的C ++ 03代碼(最多10個模板參數)。 主要技巧是為Counter類提供多重繼承,並將Counter類型的對象傳遞給必須選擇基類的函數模板。 實際求和是遞歸完成的。
Counter.hpp
enum CountedType { A, B };
template <CountedType Type, int N>
struct Counted {};
struct DummyCounted {};
template <int Pos, typename T>
struct IndexedType {};
template <unsigned int Terms>
struct PartialSum
{
template <typename CounterT>
static int getSum(const CounterT& ctr)
{ return PartialSum<Terms-1>::getSum(ctr) + ctr.template GetNAt<Terms>(); }
};
template <> struct PartialSum<0U>
{
template <typename CounterT>
static int getSum(const CounterT& ctr)
{ return ctr.template GetNAt<0>(); }
};
template <typename T0, typename T1=DummyCounted,
typename T2=DummyCounted, typename T3=DummyCounted,
typename T4=DummyCounted, typename T5=DummyCounted,
typename T6=DummyCounted, typename T7=DummyCounted,
typename T8=DummyCounted, typename T9=DummyCounted>
class Counter :
public IndexedType<0, T0>, public IndexedType<1, T1>,
public IndexedType<2, T2>, public IndexedType<3, T3>,
public IndexedType<4, T4>, public IndexedType<5, T5>,
public IndexedType<6, T6>, public IndexedType<7, T7>,
public IndexedType<8, T8>, public IndexedType<9, T9>
{
public:
static int GetTotalN() {
return PartialSum<9>().getSum( Counter() );
}
template <int Pos>
static CountedType GetTypeAt() { return _getTypeAt<Pos>( Counter() ); }
template <int Pos>
static int GetNAt() { return _getNAt<Pos>( Counter() ); }
private:
template <int Pos, CountedType Type, int N>
static CountedType _getTypeAt(const IndexedType<Pos, Counted<Type,N> >&)
{ return Type; }
template <int Pos, CountedType Type, int N>
static int _getNAt(const IndexedType<Pos, Counted<Type,N> >&)
{ return N; }
template <int Pos>
static int _getNAt(const IndexedType<Pos, DummyCounted>&)
{ return 0; }
};
Counter.cpp
#include "Counter.hpp"
#include <iostream>
typedef Counted<A, 25> CountedA;
typedef Counted<B, 7> CountedB;
class RealCounter : public Counter<CountedA, CountedB> {};
int main()
{
RealCounter counter;
int n = counter.GetTotalN();
CountedType type = counter.GetTypeAt<0>();
std::cout << "n is " << n
<< "\ntype check is " << (type == A) << std::endl;
return 0;
}
輸出:
n is 32
type check is 1
C ++ 0x可變參數模板的內容看起來很有趣,但我尚未對其進行很好的了解。 但是我確實認為在C ++ 0x中,此示例的所有功能(當然main
除外)都可以是constexpr
。
我不確定為什么您需要將這些參數嵌入模板參數中,而不是簡單地嵌入到構造函數中,因為對於每個“派生的” CountedA / B類型它們都是相同的類型。
無論如何,您都可以將結果類型嵌入到std :: tuple中,如下面的鏈接所示(有關示例,請參見Message類)。 然后在下面的鏈接中創建一個類似於applyTuple版本的可變參數模板函數,該函數將添加所有整數參數,並在所有參數展開后返回最終結果。 至於返回“ Pos”中項目的枚舉值,只需調用get(tuple).getEnum()或.value即可獲取它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.