Consider the following artificial example:
template <typename T, typename... Args>
struct A {
typedef T Type;
};
Using A
with 1 or more arguments works while using it with zero arguments fails as expected:
error: wrong number of template arguments (0, should be 1 or more)
Is it possible to make A
handle the case of zero template arguments defining A::Type
to int
if there are no arguments and to the first template argument if there are?
With the variadic templates feature, you can define class or function templates that have any number (including zero) of parameters. To achieve this goal, this feature introduces a kind of parameter called parameter pack to represent a list of zero or more parameters for templates.
A variadic template is a class or function template that supports an arbitrary number of arguments. This mechanism is especially useful to C++ library developers: You can apply it to both class templates and function templates, and thereby provide a wide range of type-safe and non-trivial functionality and flexibility.
Variadic functions are functions (e.g. std::printf) which take a variable number of arguments. To declare a variadic function, an ellipsis appears after the list of parameters, e.g. int printf(const char* format...);, which may be preceded by an optional comma.
Variadic functions are functions that can take a variable number of arguments. In C programming, a variadic function adds flexibility to the program. It takes one fixed argument and then any number of arguments can be passed.
First define the primary template as the most general case — which also includes zero argument:
template <typename... Args> //general : 0 or more
struct A { using Type = int; }
Then partially specialize it for 1 or more parameters as:
template <typename T, typename... Args> //special : 1 or more
struct A<T,Args...> { using Type = T; }
Once you have this specialization, the primary template would be used for zero-argument only!
Note that mathematically 1 or more is a special case of 0 or more — the latter is a more general case (not the other way round).
You could just add a default to the first argument, no specializations necessary:
#include <type_traits>
template <typename T = int, typename... >
struct A {
using type = T;
};
int main() {
static_assert(std::is_same<A<>::type, int>::value, "");
static_assert(std::is_same<A<double, char>::type, double>::value, "");
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With