簡體   English   中英

C ++元編程

[英]C++ metaprogramming

我有以下問題:

假設我有一些基本的計數器class Counter 並假設我們還有一些可以計數 讓我們將其中一些命名為class CountedA class CountedBclass CountedB

現在,每個可以計數的類(例如CountedACountedB都具有以下靜態聲明的部分: 一個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.

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