繁体   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