【发布时间】:2016-02-17 17:47:16
【问题描述】:
我需要专攻
template< typename T, int Id >
struct ValueTraits
{
// Default version
static int getValue() { return 0; }
};
对于某些ConcreteClass 的任何子类为T:
class ConcreteClass {};
struct ConcreteSub1: public ConcreteClass
{
static int get() { return 1; }
};
struct ConcreteSub2: public ConcreteClass
{
static int get() { return 2; }
};
对于某个预定值Id,比如123,
...这样ValueTraits< ConcreteSub1, 123 >::getValue() 将调用ConcreteSub1::get() 并返回1,而ValueTraits< ConcreteSub2, 123 >::getValue() 将调用ConcreteSub2::get() 并返回2。使用除123 之外的任何Id 或除ConcreteClass 的子类之外的类应回退到模板的默认版本。
现在,我知道我可以将std::enable_if 与std::is_base_of 一起使用,但这不需要向ValueTraits 添加额外的虚拟类型参数吗?像这样的东西会起作用,例如:
#include <stdio.h>
#include <type_traits>
template< typename T, int Id, typename Dummy = void >
struct ValueTraits
{
// Default version
static int getValue() { return 0; }
};
class ConcreteClass {};
struct ConcreteSub1: public ConcreteClass
{
static int get() { return 1; }
};
struct ConcreteSub2: public ConcreteClass
{
static int get() { return 2; }
};
template< typename T >
struct ValueTraits< T, 123, typename std::enable_if<
std::is_base_of< ConcreteClass, T >::value >::type >
{
static int getValue() { return T::get(); }
};
int main()
{
// prints 1, 2, 0
printf( "%d, %d, %d\n",
ValueTraits< ConcreteSub1, 123 >::getValue(),
ValueTraits< ConcreteSub2, 123 >::getValue(),
ValueTraits< int, 123 >::getValue() );
return 0;
}
问题是,我不能向ValueTraits 添加额外的虚拟类型参数,因为它是一个库的一部分,它实际上提供了这个ValueTraits 供我专门研究。
所以我的问题是,我可以使用 ValueTraits 的原始版本仅使用 typename 和 int 来执行此专业化吗?如何?
编辑:澄清一下,我也不是ValueTraits 的用户 - 库提供它供我专门化,然后库再次用我的类型实例化它以获得我在我的专业中定义的行为。所以我无法控制ValueTraits 的定义,也无法控制它之后的使用方式。
【问题讨论】:
-
将原始 ValueTraits 子类化为采用 3 个模板参数的扩展版本?
-
我认为这不会为 ValueTraits 本身添加任何专业化 - 请参阅编辑。
-
您需要使用哪些编译器?
-
我想说代码应该是 c++11 兼容的。我宁愿不依赖任何特定编译器的任何(错误)行为。
标签: c++ templates template-specialization sfinae enable-if