Reputation: 378
I have the following template in my C++ class:
template <typename ReturnType, typename... Args>
ReturnType run(void* context, const Args&... args) {
/* Do the actual job. */
}
For practical reason, I need to specify it for ReturnType void. I need to keep the list of args because they are still useful.
I tried the following but neither works:
template <typename... Args>
void run(void* context, const Args&... args) {
/* Do the actual job. */
}
and
template <typename ReturnType = void, typename... Args>
void run(void* context, const Args&... args) {
/* Do the actual job. */
}
So.. what is the correct way to specify with the void argument in my example?
Upvotes: 1
Views: 1746
Reputation: 303107
In C++17, this is simple: use if constexpr
:
template <typename ReturnType, typename... Args>
ReturnType run(void* context, const Args&... args) {
if constexpr (std::is_void_v<ReturnType>) {
/* void case */
} else {
/* non-void case */
}
}
Before C++17, the best way to do this is with tag dispatching. Create a new class template that just encodes the type, so that you can pass it as an argument:
template <typename T> struct tag { };
template <typename ReturnType, typename... Args>
ReturnType run_impl(tag<ReturnType>, void* context, const Args&... args) {
/* non-void case */
}
template <typename... Args>
void run_impl(tag<void>, void* context, const Args&... args) {
/* void case */
}
template <typename ReturnType, typename... Args>
ReturnType run(void* context, const Args&... args) {
return run_impl(tag<ReturnType>{}, context, args...);
}
Upvotes: 6