Why do we have to specify <> for a template cla

2019-06-17 05:49发布

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...

2条回答
叼着烟拽天下
2楼-- · 2019-06-17 06:02

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.

查看更多
何必那么认真
3楼-- · 2019-06-17 06:15

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.

查看更多
登录 后发表回答