Reputation: 1246
I am creating signature template class. I am facing a problem for "void" return type. Here is my solution to handle void return type, which is I create a template specialization class for it.
template<typename TSignature>
class CAction;
template<typename TRetType, typename... Args>
class CAction<TRetType(Args...)> {
public:
TRetType func(Args... a)
{
cout << "non void" << endl;
myPrint(a...);
cout <<"\n\n";
TRetType nRet(0);
return nRet;
}
};
template<typename... Args>
class CAction<void(Args...)> {
public:
void func(Args... a)
{
cout << "void" << endl;
myPrint(a...);
cout << "\n\n";
}
};
Below is how I initialize the class.
CAction< void(int a, int b, double c, std::string d)> on_action1;
on_action1.func(1, 2, 10.0, "a love b");
CAction< double(int a, int b, double c, std::string d)> on_action2;
on_action2.func(1, 2, 10.0, "a love b");
The code above work correctly. I am just curious, besides above method, is there any better solution ? For example : May I create a template specialization member function (func) to handle "void" return type ? Please show me code example if you know more details, thank you very much.
Upvotes: 1
Views: 157
Reputation: 96835
If you have access to C++17 you can throw in an if constexpr
and return the appropriate values in each branch:
TRetType func(Args... a) {
if constexpr(!std::is_void<TRetType>{}) {
cout << "non void" << endl;
TRetType nRet(0);
return nRet;
}
else {
cout << "void" << endl;
}
}
Otherwise you can use a tag-dispatching technique to overload based on the return type. Since specializing cannot be done with non-template functions:
template<class T>
struct type {};
TRetType func(type<TRetType>, long, Args... a) {
cout << "non void" << endl;
TRetType nRet(0);
return nRet;
}
void func(type<void>, int, Args... a) {
cout << "void" << endl;
}
TRetType func(Args... a) {
return func(type<TRetType>{}, 0, a...);
}
Upvotes: 1