2016-08-25 69 views
8

默认模板参数是否可以使用“默认值”的方式,不是从右侧开始?默认模板参数 - 不一定是从正确的?它为什么有效?

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

例如,我很惊讶,此代码工作

#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

回答

8

模板参数推导在这里很有效,因为对于函数模板,随后的模板参数可以由函数参数推导出来。在这种情况下,可以从函数参数u推导出模板参数U。请注意,对于类模板,如您预期的那样,默认模板参数之后的后续模板参数应具有默认模板参数或模板参数包。

$14.1/11 Template parameters [temp.param]

如果一个类模板,可变模板,或 别名模板的模板参数具有默认模板参数的,每个随后的 模板参数应由具有缺省模板的参数 提供或作为模板参数包。如果 主要类模板,主要变量模板或别名模板 的模板参数是模板参数包,则它应该是最后一个模板参数。 函数模板的模板参数包不能被其他模板参数跟在 之后,除非该模板参数可以是从函数 模板的参数类型列表([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 undeducible,看看会发生什么:

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; 
} 
4

你可以提供一个默认的任何参数。

如果你想使用默认,你不能明确指定参数在默认参数的右边。但是,在您的示例中,U正在从函数的参数类型中推导出来,并且T正在默认。

相关问题