C++元编程

标签 c++ templates metaprogramming

我有以下问题:

假设我有一些基本计数器 class Counter .假设我们还有一些可以计数的类集。让我们将其中一些命名为class CountedA。和 class 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 类型的对象传递给必须选择基类的函数模板。实际求和是递归完成的。

计数器.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; }

};

计数器.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

关于C++元编程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3826608/

相关文章:

C++11 quicksort terminate 在没有事件异常的情况下被调用

c++ - 错误 : ISO C++ forbids declaration of ‘iterator’ with no type

json - 使用 JSON 键作为嵌套 JSON 中的属性

用于参数分派(dispatch)的 C++ 模板元编程

c++ - 编译时间字符串散列

c++ - 最长回文子串递归解

c++ - Rcpp 代码使 R 崩溃

c++ - extern是否破坏封装

templates - Teamcity - 从模板中强制配置配置参数

python - 从特定目录继承的 Django 加载模板