If I expect a template template parameter to have one arguement then I could declare it as follows:
template<template<typename> class T>
struct S {
T<int> t_;
//other code here
}
however if I later want to provide a template template parameter which takes two arguements where the second has a default value (like std::vector) T<int> t_;
would still work but the template would not match template<typename> class T
. I could fix this by making template<typename> class T
into a variadic template template template<typename...> class T
. Now my code is more flexible.
Should I make all my template template parameters variadic in future? Is there any reason I should not (assuming C++11 support is already required for my code for other reasons)?
8. Why we use :: template-template parameter? Explanation: It is used to adapt a policy into binary ones.
A non-type template argument provided within a template argument list is an expression whose value can be determined at compile time. Such arguments must be constant expressions, addresses of functions or objects with external linkage, or addresses of static class members.
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 template argument for a template template parameter is the name of a class template. When the compiler tries to find a template to match the template template argument, it only considers primary class templates. (A primary template is the template that is being specialized.)
First, documentation. If the parameter is variadic, the user now needs to check some other source to find out that this really wants something that will takes one template parameter.
Second, early checking. If you accidentally pass two arguments to T
in S
, the compiler won't tell you if it's variadic until a user actually tries to use it.
Third, error messages. If the user passes a template that actually needs two parameters, in the variadic version the compiler will give him an error message on the line where S
instantiates T
, with all the backtrace stuff in-between. In the fixed version, he gets the error where he instantiates S
.
Fourth, it's not necessary, because template aliases can work around the issue too.
S<vector> s; // doesn't work
// but this does:
template <typename T> using vector1 = vector<T>;
S<vector1> s;
So my conclusion is, don't make things variadic. You don't actually gain flexibility, you just reduce the amount of code the user has to write a bit, at the cost of poorer readability.
If you know already that you will need it with high probability, you should add it. Otherwise, You Ain't Gonna Need It (YAGNI) so it would add more stuff to maintain. It's similar to the decision to have a template parameter in the first place. Especially in a TDD type of environment, you would refactor only when the need arises, rather than do premature abstraction.
Nor is it a good idea to apply rampant abstraction to every part of the application. Rather, it requires a dedication on the part of the developers to apply abstraction only to those parts of the program that exhibit frequent change. Resisting premature abstraction is as important as abstraction itself
Robert C. Martin Page 132, Agile Principles, Patterns and Practices in C#
The benefits of variadic templates can be real, as you point out yourself. But as long as the need for them is still speculative, I wouldn't add them.
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