Assume I have a template (called ExampleTemplate) that takes two arguments: a container type (e.g. list, vector) and a contained type (e.g. float, bool, etc). Since containers are in fact templates, this template has a template param. This is what I had to write:
#include <vector> #include <list> using namespace std; template < template <class,class> class C, typename T> class ExampleTemplate { C<T,allocator<T> > items; public: .... }; main() { ExampleTemplate<list,int> a; ExampleTemplate<vector,float> b; }
You may ask what is the "allocator" thing about. Well, Initially, I tried the obvious thing...
template < template <class> class C, typename T> class ExampleTemplate { C<T> items; };
...but I unfortunately found out that the default argument of the allocator...
vector<T, Alloc> list<T, Alloc> etc
...had to be explicitely "reserved" in the template declaration. This, as you can see, makes the code uglier, and forces me to reproduce the default values of the template arguments (in this case, the allocator).
Which is BAD.
EDIT: The question is not about the specific problem of containers - it is about "Default values in templates with template arguments", and the above is just an example. Answers depending on the knowledge that STL containers have a "::value_type" are not what I am after. Think of the generic problem: if I need to use a template argument C in a template ExampleTemplate, then in the body of ExampleTemplate, do I have to reproduce the default arguments of C when I use it? If I have to, doesn't that introduce unnecessary repetition and other problems (in this case, where C is an STL container, portability issues - e.g. "allocator" )?
You cannot give default arguments to the same template parameters in different declarations in the same scope. The compiler will not allow the following example: template<class T = char> class X; template<class T = char> class X { };
Can default arguments be used with the template class? Explanation: The template class can use default arguments.
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.)
Can there be more than one argument to templates? Yes, like normal parameters, we can pass more than one data type as arguments to templates.
Perhaps you'd prefer this:
#include <vector> #include <list> using namespace std; template <class Container> class ForExamplePurposes { typedef typename Container::value_type T; Container items; public: }; int main() { ForExamplePurposes< list<int> > a; ForExamplePurposes< vector<float> > b; }
This uses "static duck typing". It is also a bit more flexible as it doesn't force the Container type to support STL's Allocator concept.
Perhaps using the type traits idiom can give you a way out:
#include <vector> #include <list> using namespace std; struct MyFunkyContainer { typedef int funky_type; // ... rest of custom container declaration }; // General case assumes STL-compatible container template <class Container> struct ValueTypeOf { typedef typename Container::value_type type; }; // Specialization for MyFunkyContainer template <> struct ValueTypeOf<MyFunkyContainer> { typedef MyFunkyContainer::funky_type type; }; template <class Container> class ForExamplePurposes { typedef typename ValueTypeOf<Container>::type T; Container items; public: }; int main() { ForExamplePurposes< list<int> > a; ForExamplePurposes< vector<float> > b; ForExamplePurposes< MyFunkyContainer > c; }
Someone who wants to use ForExamplePurposes
with a non-STL-compliant container would need to specialize the ValueTypeOf
traits class.
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