简短版本(如果你像我一样没有耐心,请阅读):
在c++中把typename模板参数设置为默认值0有什么用?
我的enable if struct:
/**
* @brief Can be used to enable a template definition using a boolean value
*/
template<lfBool Condition>
struct lfEnableIf
{ };
template<>
struct lfEnableIf<true>
{
typedef lfInt Type;
};
My boolen constant struct:
template<lfBool Val>
struct lfBoolConstant
{
static const lfBool Value = Val;
};
typedef lfBoolConstant<true> lfTrueType;
typedef lfBoolConstant<false> lfFalseType;
我的类型trait结构(只是一个特化):
template <typename NumT> struct lfIsArithmetic : lfFalseType{};
template <> struct lfIsArithmetic<lfChar> : lfTrueType{};
最后是我的用法:
template<typename T, typename lfEnableIf<lfIsArithmetic<T>::Value>::Type = 0>
struct Test
{
static void print()
{
std::cout << "OK!" << std::endl;
}
};
int main()
{
Test<lfFloat>::print();
Test<lfBool>::print();
return 0;
}
对不起,格式不太好,我是在手机上写的。
长版本(请阅读如果你有耐心,这样你就明白为什么没有太多的代码):
所以,我在度假,不能访问我的工作站或笔记本电脑,所以我想我会尝试AIDE,如果你不知道这是一个android的IDE,可以编译c++。在家里,我正在设计一个包含Boost的游戏引擎,我想我会尝试创建一些类似于Boost中的enable_if
结构的东西。核心库。我得到了它大部分工作,但它不会编译,除非我在模板中设置启用if结构,我启用默认为0!这就是您对Boost enable_if
和disable_if
模板所做的。那么,在c++中将typename模板参数设置为默认值0有什么用呢?
谢谢!
这一行
template<typename T, typename lfEnableIf<lfIsArithmetic<T>::Value>::Type = 0>
声明了一个命名模板类型参数T
和一个命名模板值类型lfEnableIf<lfIsArithmetic<T>::Value>::Type
参数,即第二个参数声明基本上是简单
template <int N = 0> struct S {};
当满足启用条件时,类型lfEnableIf<lfIsArithmetic<T>::Value>::Type
解析为类型lfInt
,这意味着在这种情况下,整个内容相当于
template<typename T, lfInt = 0>
然而,由于第二个模板参数的类型是依赖模板lfEnableIf
的嵌套类型,因此需要使用关键字typename
告诉编译器成员Type
实际上引用的是类型,而不是其他类型(即消除歧义)。
同样,模板的第二个参数是无名的,但是如果您愿意,可以给它一个名字。它不会改变任何东西
template<typename T, typename lfEnableIf<lfIsArithmetic<T>::Value>::Type V = 0>
在上面的例子中,我称之为V
。该参数的名称不会在模板的任何地方使用,这就是为什么实际上不需要显式指定它的原因。这是一个虚拟参数,这也是它有一个虚拟默认值的原因(你可以用42
代替0
——它也不会改变任何东西)。
在这种情况下,关键字typename
在模板的两个参数声明之间创建了误导性的相似性。实际上,在这些参数声明中,关键字typename
服务于两个非常非常不同的不相关的目的。
在第一个模板参数声明typename T
中,它将T
声明为模板类型参数。关键字typename
可以替换为关键字class
template <class T, ...
在第二个声明typename lfEnableIf<lfIsArithmetic<T>::Value>::Type = 0
中,它有一个次要的目的——它只是告诉编译器lfEnableIf<lfIsArithmetic<T>::Value>::Type
是一个类型,从而把整个东西变成一个值参数声明。关键字typename
不能替换为关键字class