我正在尝试编写使用模板参数的成员typedef的代码,但是如果模板参数没有该typedef,则希望提供默认类型 . 我尝试过的一个简单示例是:
struct DefaultType { DefaultType() { printf("Default "); } };
struct NonDefaultType { NonDefaultType() { printf("NonDefault "); } };
struct A {};
struct B { typedef NonDefaultType Type; };
template<typename T, typename Enable = void> struct Get_Type {
typedef DefaultType Type;
};
template<typename T> struct Get_Type< T, typename T::Type > {
typedef typename T::Type Type;
};
int main()
{
Get_Type<A>::Type test1;
Get_Type<B>::Type test2;
}
我希望这会打印“Default NonDefault”,而是打印“Default Default” . 我的期望是main()中的第二行应该与Get_Type的专用版本匹配,因为B :: Type存在 . 但是,这不会发生 .
任何人都可以解释这里发生了什么,如何解决它,或另一种方法来实现相同的目标?
谢谢 .
编辑:
格奥尔格提供了另一种方法,但我仍然很好奇为什么这不起作用 . 根据boost enable_if文档,为不同类型专门化模板的方法如下:
template <class T, class Enable = void>
class A { ... };
template <class T>
class A<T, typename enable_if<is_integral<T> >::type> { ... };
template <class T>
class A<T, typename enable_if<is_float<T> >::type> { ... };
这是有效的,因为enable_if <true>的类型为typedef,但enable_if <false>则不然 .
我不明白这与我的版本有什么不同,而不是使用enable_if我直接使用T :: Type . 如果T :: Type存在与上面示例中的enable_if <true> :: type不同,是否会导致选择特化?如果T :: Type不存在,那就不一样与enable_if <false> :: type不存在并导致在上面的例子中选择默认版本?
3 回答
要回答你的补充 - 你的专业化参数传递成员typedef并期望它产生
void
作为类型 . 这没有什么神奇之处 - 它只使用默认参数 . 让我们看看它是如何工作的 . 如果您说Get_Type<Foo>::type
,则编译器使用Enable
的默认参数,即void
,类型名称变为Get_Type<Foo, void>::type
. 现在,编译器检查是否有任何部分特化匹配 .部分特化的参数列表
<T, typename T::Type>
是从原始参数列表<Foo, void>
中推导出来的 . 这将推导T
到Foo
,然后将Foo
替换为专业化的第二个参数,产生<Foo, NonDefaultType>
的最终结果用于部分专业化 . 但是,它根本不匹配原始参数列表<Foo, void>
!您需要一种方法来生成
void
类型,如下所示:现在这将像您期望的那样工作 . 使用MPL,您可以使用
always
而不是tovoid
你可以通过利用SFINAE来做到这一点:
第一步:停止使用“类型”并使用mpl标准“类型” .
如果在元函数中使用“type”而不是“Type”,则不需要提取器“get_type”来转换它,在这种情况下可能只返回T.