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()'
LVL 1
glebspyAsked:
Who is Participating?

Improve company productivity with a Business Account.Sign Up

x
 
AlexFMConnect With a Mentor Commented:
Possibly you mean this:

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

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


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

  return 0;
}

I am not sure this may be compiled in all compilers, but in VC++ 7.1 it works.
0
 
stefan73Commented:
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
0
 
stefan73Commented:
glebspy,
In other words: Your T result in class A wouldn't be particularly useful.

Stefan
0
Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

 
Sys_ProgCommented:
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


0
 
Sys_ProgCommented:
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
0
 
stefan73Commented:
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
0
 
stefan73Commented:
Sys_Prog,
Looks like we had the same idea - encouraging ;-)

Stefan
0
 
Sys_ProgCommented:
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
0
 
glebspyAuthor Commented:
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.
0
 
Sys_ProgCommented:
But Yeah, it was encouraging  :-)

Amit
0
 
Sys_ProgConnect With a Mentor Commented:
Hey glebspy,

as my second post suggested, u could pass a dummy argument of template type to the member function
In this case, u don't need to make the class a templated class

Amit
0
 
glebspyAuthor Commented:
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?
0
 
glebspyAuthor Commented:
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?
0
 
AlexFMCommented:
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();}  
0
 
glebspyAuthor Commented:
Any other suggestion?
0
 
AxterCommented:
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;
}
0
 
AxterCommented:
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.
0
 
AxterCommented:
>>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.          
0
 
glebspyAuthor Commented:
thanks axter
0
 
glebspyAuthor Commented:
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.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.