Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

Template member function of non-template class specification problem

Posted on 2004-04-07
21
Medium Priority
?
768 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
  • 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
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
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 800 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 1200 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

Vote for the Most Valuable Expert

It’s time to recognize experts that go above and beyond with helpful solutions and engagement on site. Choose from the top experts in the Hall of Fame or on the right rail of your favorite topic page. Look for the blue “Nominate” button on their profile to vote.

Question has a verified solution.

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

Written by John Humphreys C++ Threading and the POSIX Library This article will cover the basic information that you need to know in order to make use of the POSIX threading library available for C and C++ on UNIX and most Linux systems.   [s…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
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 technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

972 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