为什么在C ++中为typename模板参数指定默认值0?

时间:2016-08-16 18:02:20

标签: c++ templates

简短版本(如果您没有耐心,请阅读):

在C ++中将typename模板参数设置为默认值是什么?

我的启用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;
};

我的boolen常量结构:

template<lfBool Val>
struct lfBoolConstant
{
    static const lfBool Value = Val;    
};

typedef lfBoolConstant<true> lfTrueType;
typedef lfBoolConstant<false> lfFalseType;

我的类型特征结构(只是其中一个特化):

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,如果你不知道它是一个可以编译C ++的Android的IDE。在家里,我正在设计一个包含Boost的游戏引擎,我想我会尝试创建类似于Boost.Core库中的enable_if结构的东西。我得到它主要工作但它不会编译除非我设置启用if模板中的结构我启用默认为0!这是您使用Boost enable_ifdisable_if模板执行的操作。那么在C ++中将typename模板参数设置为默认值是什么呢?

谢谢!

1 个答案:

答案 0 :(得分:8)

这一行

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。该参数的名称不会在模板中的任何位置使用,这就是为什么没有必要明确指定它的原因。它是一个虚拟参数,这也是它具有虚拟默认值的原因(您可以将0替换为42 - 它也不会改变任何内容。)

在这种情况下,关键字typename会在模板的两个参数声明之间产生误导性的相似性。实际上,在这些参数声明中,关键字typename提供了两个非常非常不同的无关目的。

在第一个模板参数声明 - typename T中 - 它将T声明为模板类型参数。在此角色中,关键字typename可以替换为关键字class

template <class T, ...

在第二个声明中 - typename lfEnableIf<lfIsArithmetic<T>::Value>::Type = 0 - 它有第二个目的 - 它只是告诉编译器lfEnableIf<lfIsArithmetic<T>::Value>::Type类型,从而将整个事物变为< em> value 参数声明。在此角色中,关键字typename不能替换为关键字class