[英]Call methods on class templatized over enum
Given the following code: 给出以下代码:
enum Fruits{ eApple, eBanana };
template<>
struct SomeFruit< eApple > {
void eatIt() { // eat an apple };
};
template<>
struct SomeFruit< eBanana > {
void eatIt() { // eat a banana };
};
Is there a way to call the explicitly specialized eatIt()
, for each of Fruits
, without having to make each call manually? 有没有一种方法可以为每个
Fruits
调用显式专门化的eatIt()
,而不必手动进行每个调用?
My definition of "make each call manually" would be: 我对“手动拨打每个电话”的定义是:
void eatAllFruits()
{
SomeFruit< eApple > apple;
apple.eatIt();
SomeFruit< eBanana > banana;
banana.eatIt();
}
Clearly with this method one has to extend eatAllFruits
everytime Fruits
is modified. 显然,使用这种方法必须在每次修改
Fruits
扩展eatAllFruits
。
My guess at this point is that you want to iterate over enum fruit automatically. 我现在的猜测是您想自动遍历枚举水果。 There is, in fact, a way to do this.
实际上,有一种方法可以做到这一点。 Have a look at this article I blogged regarding a somewhat similar problem: http://crazyeddiecpp.blogspot.com/2010/02/using-mplforeach-to-fill-tuple.html
看看我写的关于一个类似问题的这篇文章: http : //crazyeddiecpp.blogspot.com/2010/02/using-mplforeach-to-fill-tuple.html
Note the use of mpl::range and mpl::for_each. 注意mpl :: range和mpl :: for_each的使用。
Thus your eatSomeFruit() function would look something like so: 因此,您的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());
}
Firstly thanks to Noah Roberts ' answer which deserves as an upvote for being the inspiration to this answer. 首先,感谢诺亚·罗伯茨 ( Noah Roberts)的回答,这是对这一答案的启发。
Following on from his answer I extracted and refactored boost::mpl::for_each
and boost::mpl::range
to obtain what I believe is the minimal complete definition which satisfies the question's criteria. 根据他的回答,我提取并重构了
boost::mpl::for_each
和boost::mpl::range
以获得我认为是满足问题标准的最小完整定义。 It has no longer has any dependancy on Boost and is used as such: 它不再依赖Boost,因此被使用:
struct eat_fruit; // As Noah's answer
void eatAllFruit()
{
EnumIteration< Fruits, eApple, eTotal >::for_each( eat_fruit() );
}
My EnumIteration
struct is defined as below, and I welcome any comments or improvements. 我的
EnumIteration
结构定义如下,欢迎任何评论或改进。 The only notable difference to the Boost version is that the range excludes the final enum value (ie eTotal
), unlike boost::mpl::range
which includes it. 与Boost版本唯一的显着区别是,该范围不包括最终的枚举值(即
eTotal
),与boost::mpl::range
包含的值不同。
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 );
}
};
The reason they're called templates is that they're not actual code - they're templates that tell the compiler what the code should look like, once you supply the missing pieces. 之所以将它们称为模板是因为它们不是实际的代码-它们是模板,一旦您提供缺少的部分,它们就会告诉编译器代码的外观。 There's no way to get the compiler to create the code without writing some other code that calls it explicitly.
没有编写其他一些明确调用它的代码,就无法让编译器创建代码。
Maybe make use of a template function? 也许利用模板功能?
template<typename F> void eatIt(F f) { /* eat it */ }
[@Dave] [@Dave]
enum somename
{
val1 = -1,
val2, // this will be = 0
...
};
somename is now a 'type' (the val# are int - they can be negative numbers) and you can use it to create variables of the type somename. somename现在是一个“类型”(val#是int-它们可以是负数),您可以使用它来创建somename类型的变量。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.