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...
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>()
andmyFunction<false>()
are both related to the extent they'll participate in the same overload set,myClass<true>
andmyClass<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.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)
Otherwise, I think using
typedef
(as per Remy's comment) is the best option.myClass
is a class template, not a class. OnlymyClass<true>
, ormyClass<>
, is a class.Similarly,
myFunction
is a function template, not a function. However, when you're invoking a templated 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 expressionmyFunction();
is valid, and the first argument is deduced asfalse
. It's just that the deduction happens thanks to the default argument rather than matching against function arguments.