2

I have a function taking, as an argument, a template class with multiple parameters (see 'func2' in the following code). I'd like the function to be able to take as argument a class inheriting from the agument type, and automatically resolve template types by upcasting. In the following example, it's ok for function 'func1', but it's apparently not possible straightforwardly when argument is a multiple template class as for function 'func2'.

The error message states: "Candidate template ignored: substitution failure : template template argument has different template parameters than its corresponding template template parameter" I understand (and kind of agree) with the message. But this is the same case for 'func1', and it's working fine.

So my question is, is there a way I can treat variable 'd' as type 'C' by automatic upcasting when using a function ? And if so, how ? I'm using Xcode 5.1.1, clang-503.0.40. and C++11 option. Thanks

template <class T1>
class A {};

class B : public A<int> {};

template <template <class T1> class T, class T1 >
void func1(T<T1> _arg) {}

template <class T1, class T2>
class C {};

template <class T1>
class D : public C<T1,int> {};

template <template <class T1, class T2> class T, class T1, class T2>
void func2(T<T1,T2> _arg) {}


int main() {
    A<int> a;
    B b;
    func1(a);//works
    func1(b);//works, T1 is resolved

    C<float,int> c;
    D<float> d;
    func2(c);//works
    func2(d);//doesn't work,compilation error message: "Candidate template ignored: substitution failure : template template argument has different template parameters than its corresponding template template parameter"

    return 0;
}
Vaughn Cato
  • 63,448
  • 5
  • 82
  • 132
brahmin
  • 568
  • 1
  • 5
  • 17
  • 1
    I got also error for `func1(b)` [Demo](https://ideone.com/4oeBpH). – Jarod42 Oct 14 '14 at 09:57
  • `func1(b);//works` << I dont believe it will compile. Which compiler are you using? – Nawaz Oct 14 '14 at 10:09
  • clang, but I forgot to mention I use C++11, maybe this is why. Adding this in the main post. – brahmin Oct 14 '14 at 10:14
  • i think you should do it step by step : let the compilo know the base class of your derived class : like this http://stackoverflow.com/questions/8709340/can-the-type-of-a-base-class-be-obtained-from-a-template-type-automatically , then seeing if the base class is of type T (and that's the part i'm blocking on) – CollioTV Oct 14 '14 at 10:48

2 Answers2

1

No, there's no way to do what you're trying to do.

You can use an alias though, assuming your compiler supports them:

template < typename T >
using D = C<T,int>;

I believe that should match your function template just fine.

If you're trying to have D have different behavior then you'd create a partial specialization of C.

Edward Strange
  • 40,307
  • 7
  • 73
  • 125
  • Yes it's a good idea. But I want to avoid at all cost partial specialization. But the typedef approach approach gave me an idea. I'm writing it in an answer. – brahmin Oct 14 '14 at 13:32
0

Ok so the best option I found is as follow. The idea is to make 'D' believe it's a multiple template class, but in fact one of the template parameters is only meant to be a specific type (int). This way, 'D2' is sort of both a one template class and two template class. There's still one partial specialization when defining template class D , but it's actually only the normal definition of class D.

template <class T1, class T2>
class C {};

template <class T1, class T2=int>
class D;

template <class T1>
class D<T1,int> : public C<T1,int> {};

template <typename T1>
using D2 = D<T1>;

template <template <class T1, class T2> class T, class T1, class T2>
void func2(T<T1,T2> _arg) {}

int main()
{
    C<float,int> c;
    D2<float> d;
    func2(c);//works
    func2(d);//works

    //instantiation tests:
    D<float> test1;//works -> normal
    D<float, int> test2;//works -> not ideal but well ok
    D<float, float> test3;//doesn't work -> also normal. States: "Implicit instantiation of undefined template 'D<float, float>' "

    return 0;
}
brahmin
  • 568
  • 1
  • 5
  • 17