默认模板参数 - 不必来自右边?为什么会这样?

时间:2016-08-25 05:26:09

标签: c++ templates default-parameters

默认模板参数是否可以使用"默认值"以一种不从右边开始的方式?

标准是什么?
编译器将如何解释?

例如,我很惊讶此代码有效

#include <iostream>
using namespace std;

template <bool T=true, class U>   //"default" from LEFT-most parameter
void f(U u){
    if(T){ cout<<true;}
    else cout<<false;
}
int main() {
    auto x = []( ){  };
    f(x);
    return 0;
}

点击此处观看现场演示:https://ideone.com/l6d9du

2 个答案:

答案 0 :(得分:8)

模板参数推导在这里运行良好,因为对于函数模板,后续模板参数可能由函数参数推导出来。在这种情况下,模板参数U可以从函数参数u中推导出来。请注意,对于类模板,如您所料,默认模板参数后面的后续模板参数应具有默认模板参数或模板参数包。

$14.1/11 Template parameters [temp.param]

  

如果是类模板,变量模板或模板参数   别名模板有一个默认的模板参数,每个后续   template-parameter应具有默认的template-argument   提供或是模板参数包。如果是模板参数的话   主类模板,主变量模板或别名模板   是模板参数包,它应该是最后一个模板参数。   不应遵循功能模板的模板参数包   通过另一个模板参数,除非该模板参数可以   从函数的参数类型列表([dcl.fct])推导出来   模板或具有默认参数([temp.deduct])。一个模板   扣除指南模板的参数([temp.deduct.guide])即   没有默认参数应该可以从中推导出来   扣除指南模板的参数类型列表。 [例如:

template<class T1 = int, class T2> class B;   // error

// U can be neither deduced from the parameter-type-list nor specified
template<class... T, class... U> void f() { } // error
template<class... T, class U> void g() { }    // error
     

- 结束示例]

您可以尝试使U无法识别,看看会发生什么:

template <bool T=true, class U>   //"default" from LEFT-most parameter
void f(){
    if(T){ cout<<true;}
    else cout<<false;
}
int main() {
    f();            // Fail. Can't deduce U.
    f<true>();      // Fail. Can't deduce U.
    f<true, int>(); // Fine. T=true, U=int.
    return 0;
}

请注意,您必须明确指定所有模板参数才能使代码正常工作,这使得默认模板参数毫无意义。如果您想让f()f<true>()正常工作,您还需要为U提供一个默认模板参数(或使其成为模板参数包)。

template <bool T=true, class U=int>
void f(){
    if(T){ cout<<true;}
    else cout<<false;
}
int main() {
    f();              // Fine. T=true,  U=int
    f<false>();       // Fine. T=false, U=int
    f<false, char>(); // Fine. T=false, U=char
    return 0;
}

答案 1 :(得分:4)

您可以为任何参数提供默认值。

如果要使用默认值,则无法在默认参数的右侧显式指定参数。但是,在您的示例中,U是从函数的参数类型推断出来的,而T是默认的。