I'm currently working on cleaning up an API full of function templates, and had a strong desire to write the following code.
template <typename T, typename U, typename V>
void doWork(const T& arg1, const U& arg2, V* optionalArg = 0);
When I invoke this template, I would like to do so as follows.
std::string text("hello");
doWork(100, 20.0, &text);
doWork('a', text); // oops!
doWork<char, std::string, void>('a', text); // to verbose!
Unfortunately, the second invocation doesn't compile since the compiler cannot deduce the type of the optional parameter. This is unfortunate, since I really don't care what the parameter type is, but rather that its value is NULL. Also, I'd like to avoid the route of the third invocation since it hampers readability.
This lead me to try to make the template argument V
have a default type, which also doesn't work since you cannot apply a default type to a function template argument (at least using VC++ 9.0).
template <typename T, typename U, typename V = void> // oops!
void doWork(const T& arg1, const U& arg2, V* optionalArg = 0);
My only remaining option is to introduce an overload of doWork
that knows nothing of the template argument V
.
template <typename T, typename U>
void doWork(const T& arg1, const U& arg2)
{
doWork(arg1, arg2, 0);
}
template <typename T, typename U, typename V>
void doWork(const T& arg1, const U& arg2, V* optionalArg);
Is this the best approach to solving this problem? The only drawback I see is that I could potentially introduce many trivial forwarding functions if a function template contains many parameters that have suitable defaults.
I think that your forwarding function is a perfectly suitable solution, although in your solution, won't you have to explicitly specify the template parameters? (0 is an integer constant that can be coverted to any V*
type.) Also doWord
vs doWork
?
As a general rule, try to avoid optional parameters where they don't have a very strong pay-off.
It might be easier to force clients of you function to just add a , (void*)0
if appriopriate than add to much extra mechanism to support both a two parameter and a three parameter version of the template. It depends on the expected uses, though.