REALFREE
REALFREE

Reputation: 4406

C++ using function template in class template

template <int C> class MyClass;

...     


template <int C>
double trans(MyClass<C> &a)
{
    //return some double 
}

//this is supposed to be function template
template <int C>
double func(MyClass<2> &a)
{
    //return some double
}

template <int C>
MyClass<C-1> func(MyClass<C> &a)
{
    MyClass<C-1> ret;
    return ret;
}

template <int C>
double otherFunc(MyClass<C> &a)
{
     double result;
     if(C == SOME_CONSTANT)
         result = func(a);
     else
         result = trans(func(a));

}

What my problem is I want to check template argument C in parameter otherFunc call function template func (return double) instead of member function of class template func(return MyClass). But somehow compiler attempts to func that returns MyClass in

     if(C == SOME_CONSTANT)
         result = func(a);

this part so I got compiler error (because double = MyClass is not viable). How should I fix this problem?

Upvotes: 0

Views: 117

Answers (2)

Tony Delroy
Tony Delroy

Reputation: 106246

Hard to elaborate in a comment, so I'll post an answer. To recap what I said in comments:

  • you can't have an if/else in otherFunc that won't be legal to compile for a specific MyClass instantiation,
  • you can use the same template specialisation approach to create an alternative otherFunc definition to handle MyClass<2>s.

Sample code:

#include <iostream>

template <int C>
class MyClass
{ };

template <int C>
double trans(const MyClass<C> &a)
{
    return C + 700;
}

template <int C>
MyClass<C-1> func(MyClass<C> &a)
{
    MyClass<C-1> ret;
    return ret;
}


double func(MyClass<2>& a)
{
    return 200.0;
}

template <int C>
double otherFunc(MyClass<C> &a)
{
     return trans(func<C>(a));
}

template <>
double otherFunc<2>(MyClass<2>& a)
{
    return func(a);
}


int main()
{
    MyClass<2> a;
    std::cout << otherFunc(a) << '\n';

    MyClass<4> b;
    std::cout << otherFunc(b) << '\n';
}

Output:

200
703

Upvotes: 0

Mateusz Kubuszok
Mateusz Kubuszok

Reputation: 27595

I guess the reason is that:

 if(C == SOME_CONSTANT)
     result = func(a);
 else
     result = trans(func(a));

is checked in the runtime, while template specializations and type check is done during compilation. Those 2 functions:

 template <int C>
 double func(MyClass<2> &a)
 {
     //return some double
 }

 template <int C>
 MyClass<C-1> func(MyClass<C> &a)
 {
     MyClass<C-1> ret;
     return ret;
 }

have almost the same signatures - the only difference is that for C==2 is used the one returning double, otherwise used the one returning MyClass<2>. So what you get is:

 // for C==2
 if(C == SOME_CONSTANT)
     result = func<2>(a); // returns double - just like you wanted
 else
     result = trans<2>(func<2>(a)); // pass double into trans<?>(MyClass<?>), so the parameter cannot be resolved unless you specified some implicit constructor/explicit conversion operator 

 // for e.g. C==3
 if(C == SOME_CONSTANT)
     result = func<3>(a); // returns MyClass<2> while result is double
 else
     result = trans<2>(func<3>(a)); // pass MyClass<2> into trans<?>(MyClass<>) - like you wanted

so basically your code have invalid type for specializations in either first or second case. You can do something like this instead:

 template <>
 MyClass<2> func<2>(MyClass<2> &a)
 {
     return a;
 }

 template <int C>
 MyClass<C-1> func(MyClass<C> &a)
 {
     return MyClass<C-1>;
 }

to keep templates type consistent, and then:

if(C == SOME_CONSTANT)
   result = trans(a);
else
   result = trans(func(a));

It's just an example how to handle it. Things should be easier if you avoid messing with different return typed for different template specializations.

Upvotes: 0

Related Questions