代码之家  ›  专栏  ›  技术社区  ›  Yippie-Ki-Yay

C++元程序设计

  •  1
  • Yippie-Ki-Yay  · 技术社区  · 16 年前

    我有以下问题:

    假设我有一些基本的柜台 class Counter . 假设我们还有一些 类,可以计数。 我们来列举一些 class CountedA 和 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 .

    2 回复  |  直到 14 年前
        1
  •  1
  •   aschepler    16 年前

    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; }
    
    };
    

    #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
    

    main constexpr