Why do we have to specify <> for a template class with default parameters?

蓝咒 提交于 2019-12-08 19:12:19

问题


I find something annoying in C++ and I don't know if there is a trick to avoid this with no overhead. The problem is the following :

For a template function, we can have :

// Function declaration/definition
template<bool Option = false> void myFunction() 
{
    std::cout<<"Option = "<<Option<<std::endl;
}

// Then I can use :
myFunction<false>();
myFunction<true>();
myFunction(); // <- NO PROBLEM HERE

Now for a template class :

// Class definition/declaration
template<bool Option = false> class MyClass
{
};

// Then I can use :
myClass<false> x;
myClass<true> y;
myClass z; // <- PROBLEM HERE : only "MyClass<> z;" will compile !

Why is the reason of this behaviour ? Is there any trick to avoid that ? For a class with optionnal parameters passed as template, I find this not convenient for the end user : he should be able to use the default implementation as a no-templated class...


回答1:


Why is the reason of this behaviour ?

It's because functions can be overloaded, and types can't.

When you write a function call, the compiler populates an overload set of all the functions it can find with that name, and then figures out which ones match the argument(s) passed. Now, for this to work cleanly with function templates, it allows the template argument types to be deduced from the parameters. Because type parameter inference is allowed in general, it works for your case even when the parameter is defaulted instead.

Types, however, aren't overloaded. While myFunction<true>() and myFunction<false>() are both related to the extent they'll participate in the same overload set, myClass<true> and myClass<false> are separate and unrelated types. With no equivalent of overloading on type names, there's no motivation to add a special case for implicitly naming a fully-specialized template class. The parameters can never be inferred, so it would amount to special syntax only for the case where they're all defaulted.

Is there any trick to avoid that ?

In general, if you want to get template argument deduction for template classes, you can provide a template function wrapper (this works best with C++11 auto)

template <bool Option=false> class MyClass {};
template <bool Option=false> MyClass<Option> make_my_class() {
    return MyClass<Option>();
}
// ...
auto z = make_my_class();

Otherwise, I think using typedef (as per Remy's comment) is the best option.




回答2:


myClass is a class template, not a class. Only myClass<true>, or myClass<>, is a class.

Similarly, myFunction is a function template, not a function. However, when you're invoking a temp­la­ted function, the template arguments may be deduced for you, and you don't need to specify template arguments explicitly if they can be deduced. Thus the function call expression myFunction(); is valid, and the first argument is deduced as false. It's just that the deduction happens thanks to the default argument rather than matching against function arguments.



来源:https://stackoverflow.com/questions/12755947/why-do-we-have-to-specify-for-a-template-class-with-default-parameters

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!