Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

like image 263
Vincent Avatar asked Oct 06 '12 01:10

Vincent


1 Answers

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.

like image 186
Useless Avatar answered Nov 15 '22 10:11

Useless