Template functions cannot be partially specialized. There are different things that you can do: you can wrap the function into a class template with a single static method and specialize the class template, or you can use SFINAE to select the best choice of function among different template functions:
template <typename O, typename Args...>
void single_op_wrapper( /* all but failval */ ) { // [+]
// implementation for void
}
template <typename R, typename O, typename Args...>
typename boost::enable_if< boost::is_same<R,bool>, bool >::type // bool if condition is met
single_op_wrapper( /* all args */ ) {
// implementation for R being a bool
}
template <typename R, typename O, typename Args...>
typename boost::enable_if< boost::is_same<R,char> >::type // by default bool
single_op_wrapper( /* all args */ ) {
// implementation for void return
}
template <typename R, typename O, typename Args...>
typename boost::disable_if_c< boost::is_same<R,char>::value //[*]
|| boost::is_same<R,bool>::value
, R >::type
single_op_wrapper( /* all args */ ) {
// implementation when R is neither bool nor void
}
On the separate template for void [+]:
In C++ you cannot have a function that takes an argument of type void
. That means that you cannot use the same arguments for the void
case as you are using for the rest of them.
On the metaprogramming side:
There are a couple of tricky bits here... the enable_if
is a metafunction that defines an internal type if the condition is met or nothing otherwise. When the compiler tries to substitute the types in the template, the return type will only be valid (and as such the function be a candidate) if the condition is met. The disable_if
metafunction has the opposite behavior. The straight variant enable_if
/ disable_if
take a metafunction as first argument and optionally a type as second argument. The second version enable_if_c
/ disable_if_c
take a boolean as first argument.
It is important in [*] to note that the functions must be exclusive. That is, if for a given type more than one of the templates are candidates, as none of them is an specialization of the others, the compiler will stop with an ambiguity error. That is the reason for using the disable_if
in the last template.
Note: I have used boost
namespace instead of std
as I have not played ever with metaprogramming in c++0x, but I believe that you can change the boost
namespace with std
in your compiler. Check the docs in advance!