Saurabh Manchanda
Saurabh Manchanda

Reputation: 1125

Getting absurd errors in using template template arguments

I have been trying to create a templated class(Test2) that takes 2 template arguments,Type1 and Type2. It is known that the second argument would also be a templated class that takes 2 template arguments(TypeA and TypeB).

Now, for constructing an object of Test2, I want the user to be able to use either of 2 types of constructors:

  1. One that takes objects of Type1 and Type2.
  2. One that takes objects of Type1, TypeA and TypeB.

I wrote the following code:

#include <iostream>

template<class TypeA, class TypeB>
struct Test
{
    TypeA t1obj;
    TypeB t2obj;
    Test(const TypeA& t1, const TypeB& t2)
        : t1obj(t1), t2obj(t2) {std::cout<<"Test::Type1, Type2\n";}
};


template<class Type1,
         template<typename TypeX, typename TypeY> class Type2 >
struct Test2
{
    Type1 t1obj;
    Type2<typename TypeX, typename TypeY> t2obj; //Line 17

    Test2(const Type1& t1,
          const Type2<typename TypeX, typename TypeY>& t2) //Line 20
        : t1obj(t1), t2obj(t2) { std::cout<<"Test2::Type1, Type2\n";}

    Test2(const Type1& t1,
          const TypeX& x,
          const TypeY& y)
        : t1obj(t1), t2obj(x,y) { std::cout<<"Test2::Type1, X, Y\n";}

};

int main()
{
    Test<int, char> obj1(1,'a');

    Test2<int, Test<int, char> > strangeobj1(10,obj1);
    Test2<int, Test<int, char> > strangeobj2(1,2,'b');

}

I have tried a lot but I get really absurd errors like:

wrong number of template arguments (1, should be 2) on Line 17 and 20.

Upvotes: 1

Views: 265

Answers (5)

Johannes Schaub - litb
Johannes Schaub - litb

Reputation: 507403

It doesn't work like that. Test<int, char> is a full blown type, instead of a template. So you need type parameters

template<class Type1,
         class Type2 >
struct Test2
{
    Type1 t1obj;
    Type2 t2obj; //Line 17

    Test2(const Type1& t1,
          const Type2& t2) //Line 20
        : t1obj(t1), t2obj(t2) { std::cout<<"Test2::Type1, Type2\n";}

    Test2(const Type1& t1,
          const typename Type2::a_type& x,
          const typename Type2::b_type& y)
        : t1obj(t1), t2obj(x,y) { std::cout<<"Test2::Type1, X, Y\n";}

};

For getting TypeX and TypeY it's useful to export them so you can use them in Test2 as shown above.

template<class TypeA, class TypeB>
struct Test
{
    typedef TypeA a_type;
    typedef TypeB b_type;

    // and using them, to show their meaning
    a_type t1obj;
    b_type t2obj;

    Test(const a_type& t1, const b_type& t2)
        : t1obj(t1), t2obj(t2) {std::cout<<"Test::Type1, Type2\n";}
};

Be sure to read Where to put the "template" and "typename" on dependent names to understand why and when to use typename before type names like above.

Upvotes: 6

Ben Voigt
Ben Voigt

Reputation: 283921

Test<int, char> is not a match for template<typename TypeX, typename TypeY> class Type2

The first one is an instantiation of a template class, it does not accept any parameters. The second one is a template class pattern accepting two parameters.

Upvotes: 0

sbi
sbi

Reputation: 224189

There are several errors with this, but the main error seems to be that

Test2<int, Test<int, char> >

is not how you pass a template template parameter. This would be passed using

Test2<int, Test>

That is because Test is a template but Test<int, char> is a type (generated from that template.)

Upvotes: 1

Reinderien
Reinderien

Reputation: 15328

Here's one option:

#include <iostream>

template<class TypeA, class TypeB>
struct Test
{
    TypeA t1obj;
    TypeB t2obj;
    Test(const TypeA& t1, const TypeB& t2)
        : t1obj(t1), t2obj(t2) {std::cout<<"Test::Type1, Type2\n";}
};


template<class Type1, typename TypeX, typename TypeY,
         template <typename TypeXi, typename TypeYi> class Type2>
struct Test2
{
    Type1 t1obj;
    Type2<typename TypeX, typename TypeY> t2obj; //Line 17

    Test2(const Type1& t1,
          const Type2<typename TypeX, typename TypeY>& t2) //Line 20
        : t1obj(t1), t2obj(t2) { std::cout<<"Test2::Type1, Type2\n";}

    Test2(const Type1& t1,
          const TypeX& x,
          const TypeY& y)
        : t1obj(t1), t2obj(x,y) { std::cout<<"Test2::Type1, X, Y\n";}

};

int main()
{
    Test<int, char> obj1(1,'a');

    Test2<int, int, char, Test> strangeobj1(10,obj1);
    Test2<int, int, char, Test> strangeobj2(1,2,'b');

}

Upvotes: 0

fredoverflow
fredoverflow

Reputation: 263360

Type1 is a type, Type2 is a template. What exactly do you think TypeX and TypeY are defined? Inside the line template<typename TypeX, typename TypeY> class Type2 >, they are ignored.

Upvotes: 0

Related Questions