Solved

Template member function of non-template class specification problem

Posted on 2004-04-07
21
763 Views
Last Modified: 2008-01-09
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()'
0
Comment
Question by:glebspy
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 5
  • 4
  • +2
21 Comments
 
LVL 12

Expert Comment

by:stefan73
ID: 10774275
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
 
LVL 12

Expert Comment

by:stefan73
ID: 10774287
glebspy,
In other words: Your T result in class A wouldn't be particularly useful.

Stefan
0
 
LVL 10

Expert Comment

by:Sys_Prog
ID: 10774329
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
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 10

Expert Comment

by:Sys_Prog
ID: 10774367
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
 
LVL 12

Expert Comment

by:stefan73
ID: 10774376
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
 
LVL 12

Expert Comment

by:stefan73
ID: 10774382
Sys_Prog,
Looks like we had the same idea - encouraging ;-)

Stefan
0
 
LVL 10

Expert Comment

by:Sys_Prog
ID: 10774429
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
 
LVL 1

Author Comment

by:glebspy
ID: 10774431
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
 
LVL 10

Expert Comment

by:Sys_Prog
ID: 10774438
But Yeah, it was encouraging  :-)

Amit
0
 
LVL 10

Assisted Solution

by:Sys_Prog
Sys_Prog earned 200 total points
ID: 10774444
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
 
LVL 48

Accepted Solution

by:
AlexFM earned 300 total points
ID: 10774462
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
 
LVL 1

Author Comment

by:glebspy
ID: 10774470
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
 
LVL 1

Author Comment

by:glebspy
ID: 10774494
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
 
LVL 48

Expert Comment

by:AlexFM
ID: 10774565
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
 
LVL 1

Author Comment

by:glebspy
ID: 10774599
Any other suggestion?
0
 
LVL 30

Expert Comment

by:Axter
ID: 10775130
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
 
LVL 30

Expert Comment

by:Axter
ID: 10775153
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
 
LVL 30

Expert Comment

by:Axter
ID: 10775201
>>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
 
LVL 1

Author Comment

by:glebspy
ID: 10775203
thanks axter
0
 
LVL 1

Author Comment

by:glebspy
ID: 10775274
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

Featured Post

Ready to get started with anonymous questions?

It's easy! Check out this step-by-step guide for asking an anonymous question on Experts Exchange.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In days of old, returning something by value from a function in C++ was necessarily avoided because it would, invariably, involve one or even two copies of the object being created and potentially costly calls to a copy-constructor and destructor. A…
Templates For Beginners Or How To Encourage The Compiler To Work For You Introduction This tutorial is targeted at the reader who is, perhaps, familiar with the basics of C++ but would prefer a little slower introduction to the more ad…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

635 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question