Link to home
Start Free TrialLog in
Avatar of glebspy
glebspy

asked on

Template member function of non-template class specification problem

Why doesn't this work? How can I change it to make it work?

code is

class A
{
public:
  template<typename T>
  T f(void){T result; return result;}
};

template<typename T>
class B
{
public:
   T g(void){A a;return a.f();}
};

int main(void)
{
  B<int>b;
  cout<<b.g()<<endl;
  return 0;
}

error is
a.C: In member function `T B<T>::g() [with T = int]':
a.C:22:   instantiated from here
a.C:16: no matching function for call to `A::f()'
Avatar of stefan73
stefan73
Flag of Germany image

Hi glebspy,
Try to make the entire class A a template, instead of just a method. A "orphaned" template method does not make much sense, since there cannot be any opertion with it in a non-template class.

Cheers,
Stefan
glebspy,
In other words: Your T result in class A wouldn't be particularly useful.

Stefan
glebspy,

If u notice how template works,

It actually happens at compile time

Now, when u say
 B<int> b;

The templated class B is used to create a new class declaration for the class argument as 'int'
Thus, when u say
b.g() -> the call is resolved as the function of this newly generated class definition

Now, in function g(), u declare an object of class A
So far OK
When u call a.f(), this means u want to invoke the member function f() -> but no such member function exists for object of type A since the function is a templated function -
Thus, as stefan suggested, u would have to make the class A as a template class

Amit


One more solution could be to pass a parameter of type T to the function f() in class A
This would enable the compiler to identify the function f() as a member function of class A and it could pass int as the templated argument

The code as shown below

#include <iostream>

using namespace std ;

class A {
      public:
           template<typename T>
        T f(T temp){
                 T result = temp;
               return result;
      }
};

template<typename T>
class B {
      public:
         T g(void) {
            A a;
            int i = 10 ;
            return a.f(i);
       }
};



int main(int argc, char* argv[])
{
    B<int> b;
    cout<< b.g()<<endl;
    system("pause");
      return 0;
}


Amit
glebspy,
You could use a template function outside of class A:

template<typename T>
  T f(void){T result; return result;}

This should work fine, as long as the compiler can determine the T type via an argument - this could be via a dummy, like

template<typename T>
T f(const T& dummy){T result; return result;}

template<typename T>
class B
{
public:
   T g(void){T a;return f(a);}
};




Stefan
Sys_Prog,
Looks like we had the same idea - encouraging ;-)

Stefan
Stefan,

The idea was similar but not quite same
Both of us suggested to have a dummy argument of template type to the templated function
The only difference being u suggested it to be a non-member function, I sugegsted it to be a member function

Amit
Avatar of glebspy
glebspy

ASKER

In the real case, A is a string-like class which may be converted via template<typename T>T f(void) {...}  into any type T by reading from a's istringstream using << (for either builtin or non-builtin T). So I think it is useful as a template member, and I don't think it is appropriate to make A a template class.

I just want to know the correct syntax to set up this mechanism. Workarounds would be fine, but turning A into a template class is too drastic.

I also tried  return a.f<T>(); rather than return a.f(); but that didn't work either.
But Yeah, it was encouraging  :-)

Amit
SOLUTION
Avatar of Sys_Prog
Sys_Prog
Flag of India image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of glebspy

ASKER

Sysprogs dummy argument method is a genuine workaround. But I can't believe there isn't anything better. It should be a possible thing to do according to the standard shouldn't it?
Avatar of glebspy

ASKER

AlexFM yes that is precisely what I mean. It should compile, shouldn't it!

But I am usting g++ 3.2.2 and it says

a.C: In member function `T B<T>::g()':
a.C:17: parse error before `;' token

compiling the code you just posted (AlexFM).

What can I do to make the compiler agree to this?
This should compile, according to C++ specification, but there is no 100% standard compiler. If your compiler cannot do this, find another syntax, for example, make the whole A class as template:

template<typename T>
class A
{
public:
  T f(void){T result = 0; return result;}
};


T g(void){A<T> a;return a.f();}  
Avatar of glebspy

ASKER

Any other suggestion?
Avatar of Axter
Here's a modified version of Sys_Prog suggestion, which does not need to create a temporary object to pass into the function.
By using a pointer, and passing a NULL value that is cast to the target type, you can get the compiler to create the correct function type with out creating a temporary variable.

class A
{
public:
  template<typename T>
  T f(T *){T result; return result;}
};

template<typename T>
class B
{
public:
   T g(void){A a;return a.f((T*)NULL);}
};

int main(void)
{
  B<int>b;
  cout<<b.g()<<endl;
  return 0;
}
FYI:
Since there is no argument name in the f() function, the compiler can optimize away passing in the NULL value, and you don't have to worry about accidently using the NULL value pointer if the f() function.
>>a.C: In member function `T B<T>::g()':

It looks like you didn't use the correct syntax.

The first code that AlexFM posted should have compiled on the GNU compiler.
However, the above error doesn't look like you use the exact syntax.

Please post the exact modified code, so that we can get a complete picture.
This should work on the GNU compiler:
T g(void){A a;return a.f<T>();}//There's NO T before a.f<T>()

In your posted error there's a T before the function call, which shouldn't be there.          
Avatar of glebspy

ASKER

thanks axter
Avatar of glebspy

ASKER

Axter, of course there is no T before a.f<T>. You say post the exact modified code, but I didn't modify the code, I just cut and pasted AlexFM's code into a.C and recompiled it. It produced the error message.

a.C: In member function `T B<T>::g()':
just means that g()  is a member of B<T> returning a T, which is correct. So I don't see why you said "It looks like you didn't use the correct syntax".

If you really compiled AlexFM's code on the gnu compiler as you suggest, could you please tell me what version you are using and what your build details are, and I will try to reproduce your success.