Can I use std :: vector as template parameter or should it be std :: vector <T>?

I know this is a simple question, but I just couldn't find the answer.

I'm trying to do something like this, but instead of std :: vector, I end up wanting it to be std :: shared_ptr or std :: weak_ptr:

template <int dim, class ChunkClass, class PtrClass>
class BaseChunkWindow : public IChunkWindow<BaseChunkWindow<dim, ChunkClass, PtrClass>, IChunk<ChunkClass>> {
public:
...
private:
PtrClass< IChunk<ChunkClass> > ptr;  <-- compiler doesn't like this line, however IChunk<ChunkClass>* works
};

      

+2


source to share


2 answers


It depends on what you are passing it to, if the template you are trying to create takes as a parameter a class template that takes 2 (or in C ++ 11 variation number) classes, then you can pass std :: vector to that ... However, in most cases, templates require classes as parameters and you cannot pass a std :: vector class template.

    template <class T>
    struct gimme_a_type{};

    template <template <class,class> class T>
    struct gimme_a_template{};

    gimme_a_type<std::vector> //<-- does not compile, expected a type, got a template
    gimme_a_type<std::vector<int> > //<-- compiles, expected a type, got a type
    gimme_a_template<std::vector> //<-- compiles, expected a template, got a template that has the correct signature
    gimme_a_template<std::vector<int> > //<-- does not compile, expected a template, got a type

      

In response to your editing, there are difficulties with using class templates as template parameters. Matching the number of parameters exactly is actually difficult to do when you have default arguments in the class template you are trying to pass ( std::vector

in our case). Note that the above example requires a class template that takes 2 classes, not one. This is due to the fact that it std::vector

takes two parameters, the second for us by default is std::allocator<T>

.



The following example demonstrates the problem:

    template <template <class, class> class Tem>
    struct A
    {
        Tem<int> v; //<-- fails to compile on gcc, Tem takes two parameters
        Tem<int, std::allocator<int> >; //<-- compiles, but requires a priori knowledge of Tem
    };

    template <template <class...> class Tem>
    struct A2
    {
      Tem<int> v; //<-- This C++11 example will work, but still isn't perfect.
    };

      

The C ++ 11 example is better, but if someone passed in a signed class template <class, bool = false> class A3

it won't work again because it A2

requires a variable number of classes, not a variable number whatevers. So even though it A3<int>

might be a valid instance, you cannot pass that class to A2

.
The solution is to always use types in template parameter lists and use a wrapper template std::integral_constant

to pass integral constants around.

+9


source


There are several ways to do this.

The limited way is to use a template template parameter with only a limited number of parameters passed, eg. 3.

template<template<class,class,class> class Cont, class T, class V, class U>
void f(Cont<T,V,U>&& cont) {
    //...
}

      

However, this is quite limiting and can be difficult to handle if you decide to change it in the future.



So, you can do it like this using the new Variadic templates in C ++ 11:

template<template<class...> class Cont, typename F, typename... Rest>
void f(Cont<F, Rest...>&& cont) {
    //...
}

      

This will work with other containers or things and is probably much easier to manage.

+4


source







All Articles