代码之家  ›  专栏  ›  技术社区  ›  davetapley

对枚举上模板化的类调用方法

  •  1
  • davetapley  · 技术社区  · 14 年前

    给定以下代码:

    enum Fruits{ eApple, eBanana };
    
    template<>
    struct SomeFruit< eApple > {
        void eatIt() { // eat an apple };
    };
    
    template<>
    struct SomeFruit< eBanana > {
        void eatIt() { // eat a banana };
    };
    

    有没有方法调用显式专用的 eatIt() Fruits ,而不必每次都手动打电话?

    void eatAllFruits()
    {
        SomeFruit< eApple > apple;   
        apple.eatIt(); 
        SomeFruit< eBanana > banana; 
        banana.eatIt(); 
    }
    

    很明显,用这种方法我们必须扩展 eatAllFruits 每次 水果

    4 回复  |  直到 14 年前
        1
  •  4
  •   Edward Strange    14 年前

    我在这一点上的猜测是,您希望自动遍历枚举结果。事实上,有一种方法可以做到这一点。看看我在博客上写的一篇关于类似问题的文章: http://crazyeddiecpp.blogspot.com/2010/02/using-mplforeach-to-fill-tuple.html

    注意mpl::range和mpl::for_each的用法。

    因此,eatSomeFruit()函数的外观如下:

    // modify enum...
    enum Fruits { eApple, eBananna, eFruitLast = eBananna };
    
    struct eat_fruit
    {
      template < typename Index >
      void operator() (Index&)
      {
        SomeFruit<Index::value> eater;
        eater.eatIt();
      }
    };
    
    void eatSomeFruit()
    {
      mpl::for_each< mpl::range<0, eFruitLast> >(eat_fruit());
    }
    
        2
  •  1
  •   Community CDub    8 年前

    首先要感谢 Noah Roberts “这个答案应该作为这个答案的灵感的一个投票。

    boost::mpl::for_each boost::mpl::range

    struct eat_fruit; // As Noah's answer
    
    void eatAllFruit()  
    {  
        EnumIteration< Fruits, eApple, eTotal >::for_each( eat_fruit() );
    } 
    

    我的 EnumIteration struct定义如下,我欢迎任何评论或改进。与Boost版本唯一显著的不同是,该范围不包括最终的枚举值(即。 eTotal ),与 boost::mpl::范围

    template< typename ENUM, ENUM BEGIN, ENUM END >
    struct EnumIteration
    {
    private:
        template< ENUM N >
        struct Iterator
        {
            static const ENUM value = N;
            typedef Iterator< static_cast< ENUM >( N+1 ) > next;
            operator ENUM() const { return static_cast< ENUM >( this->value ); } 
        };
    
        template< typename T >
        struct End 
        { enum { value = false }; };
    
        template<>
        struct End< Iterator< END > >
        { enum { value = true }; };
    
        template< bool done = true >
        struct for_each_impl
        {
            template< typename Iterator, typename F >
            static void execute( Iterator*, F ) {}
        };
    
        template<>
        struct for_each_impl<false>
        {
            template< typename Iterator, typename F >
            static void execute( Iterator*, F f )
            {
                f( typename Iterator() );
                typedef typename Iterator::next next;
                for_each_impl< End< next >::value >::execute( static_cast< next * >( 0 ), f );
            }
        };
    
    public:
        template< typename F >
        static void for_each( F f )
        {
            typedef Iterator< BEGIN > first;
            for_each_impl< End< first >::value >::execute( static_cast< first * >( 0 ), f );
        }
    };
    
        3
  •  0
  •   Mark Ransom    14 年前

    之所以称它们为模板,是因为它们不是实际的代码——它们是告诉编译器代码应该是什么样子的模板,一旦你提供了丢失的部分。没有办法让编译器在不编写其他显式调用它的代码的情况下创建代码。

        4
  •  0
  •   slashmais    14 年前

    也许使用模板函数?

    template<typename F> void eatIt(F f) { /* eat it */ }
    

    [@戴夫]

    enum somename
    {
    val1 = -1,
    val2, // this will be = 0
    ...
    };
    

    somename现在是一个“type”(val#是int-它们可以是负数),您可以使用它创建somename类型的变量。