开发者

Instantiate a template class <erroneous-expression>?

开发者 https://www.devze.com 2023-03-31 04:52 出处:网络
Here is my code : template<typename T, template<typename = T,typename =std::allocator<typename = T> > class Container= std::vector>

Here is my code :

template<typename T, template<typename = T,typename =std::allocator<typename = T> > class Container= std::vector>
 class stack
 {
     public:
     Container<T> cont;
     stack()
     {

     }
 };

If i replace the very first line of code to be开发者_Python百科low code then it works :

template<typename T, template<typename elem= T,typename =std::allocator<elem> > class Container= std::vector>

but i want to ask that i've read when you don't use templates type parameter then you can write this : <typename=default_type> or <typename> . Also T in above code is visible in parameter list of template template parameter Container ( i.e type parameter T is visible in it's whole parameterization clause ). so all in all i think so it should work. but it doesn't and gives the error :

error: expression '<erroneous-expression> = <erroneous-expression>' is not a constant-expression
error: template argument 1 and 2 are invalid

So can anyone explain why i am seeing these errors, what is erroneous-expression?


When a template parameter is itself a template, then its own template parameters are not used or relevant in the context of the outer template other than to define the "template signature" of the template-template parameter. Therefore, you don't need neither parameter names, as they are not usable or necessary. You can simply say this:

template <typename T, template<typename, typename> class Container = std::vector>
class stack
{
  typedef Container<T, std::allocator<T> > CT;
  // ...
};

Here template <typename, typename> is just the template signature of the Container template class that you expect.

In C++11 you can do better and allow more general containers by using variadic templates:

template <typename T, template<typename...> class Container = std::vector> class stack;

[For completeness:] Putting default types in the template parameter's parameter list also works, and it means you can omit those types later (as you already do):

template<typename = T, typename = std::allocator<T> > class Container

---> now we can say:

Container<T> x;  // use second default argument
Container<> y;   // use both default arguments

To answer your question: You want to specify a default type in

 template <typename = T, typename = std::allocator<typename> > class Container
                                    ^^^^^^^^^^^^^^^^^^^^^^^^
                                            Error!!

but std::allocator<typename> isn't a type -- it's not even legal syntax. You could either have a template parameter which once again is a template, i.e. template <typename> = std::allocator, but that wouldn't be matched by std::vector, or you have an actual type:

template <typename = T, typename = std::allocator<T> > class Container
                                   ^^^^^^^^^^^^^^^^^
                                   OK, this is a type


In the parameter-list of a class template, when you specify template template parameter , then template parameter of the template template parameter is not used (in fact, they cannot be used). As such, you can skip mentioning even their names.

So what you should be doing is this:

template<typename T, template<class,class> class Container= std::vector>
class stack
{
     Container<T, std::allocator<T> > cont;
};

That is, all that is required for the template template parameter is the number of parameter(s), and the information what their parameter(s) : type or value.

You can also write this for better readability:

template<typename T, template<class U,class Allocator> class Container= std::vector>
class stack
{
     Container<T, std::allocator<T> > cont;
};

As for why your first code is not working, because of std::allocator<typename = T> which should be simply std::allocator<T>. That is, this should work:

template<typename T, template<typename =T,typename =std::allocator<T> >  class Container= std::vector>

See it here : http://ideone.com/eO8qT

But then such default types of the template template parameter is not even considered. They're ignored.

Now you might ask why std::allocator<typename =T> doesn't work. Because its ill-formed. Do you think std::vector<typename =T> makes any sense? Please note that std::allocator and std::vector both are class template, but Container is not a class template. Its a template template parameter of a class template. That is why, typename =T is allowed for this, while its not allowed for class templates such as std::allocator.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号