Question

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.

Was it helpful?

Solution

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.

OTHER TIPS

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.)

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.

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');

}

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top