Search code examples
c++c++11templatesconstructortemplate-templates

Cannot call constructor (template-template parameter)


Somehow I can't create an instance of D. I don't know why. The template-template parameter (Allocator_class) seems to be the problem.

#include <vector>

template <template<typename T> class Allocator_class>
class T_b {
public:
    template<typename T> using A = Allocator_class<T>;
};

template< template <typename T> class A>
class C {
public:
    C() { }
};

template<typename Ttb>
class D {
public:
    template<typename T> using A = typename Ttb::template A<T>;
    typedef C<A> Data;

    D(C<A> &data) : _data(data) {}
private:
    Data &_data;
};

int main() {
    typedef T_b<std::allocator> Ttb;    
    C<std::allocator> b;
    D<Ttb>c(b);
}

Error from Clang:

test5.cpp:29:8: error: no matching constructor for initialization of 'D<Ttb>'
      (aka 'D<T_b<std::allocator> >')
        D<Ttb>c(b);
              ^ ~
test5.cpp:16:7: note: candidate constructor (the implicit copy constructor) not viable: no known
      conversion from 'C<std::allocator>' to 'const D<T_b<std::allocator> >' for 1st argument
class D {
      ^
test5.cpp:16:7: note: candidate constructor (the implicit move constructor) not viable: no known
      conversion from 'C<std::allocator>' to 'D<T_b<std::allocator> >' for 1st argument
class D {
      ^
test5.cpp:21:5: note: candidate constructor not viable: no known conversion from 'C<std::allocator>'
      to 'C<A> &' for 1st argument
    D(C<A> &data) : _data(data) {}
    ^

Solution

  • I can't explain why your code gives an error.

    But if you want a solution... using a class specialization and a template template template parameter....

    #include <vector>
    
    template <template<typename T> class Allocator_class>
    class T_b
     {
       public:
          template<typename T> using A = Allocator_class<T>;
     };
    
    template <template <typename T> class A>
    class C
     {
       public:
          C() { }
     };
    
    template <typename>
    class D;
    
    template <template <template <typename> class> class X,
              template <typename> class A>
    class D<X<A>>
     {
       public:
          using Data = C<A>;
    
          D (Data & data) : _data(data) {}
    
       private:
          Data & _data;
     };
    
    int main()
     {
        typedef T_b<std::allocator> Ttb;    
    
        C<std::allocator> b;
    
        D<Ttb> c(b);
     }