Solved

Template member function of non-template class specification problem

Posted on 2004-04-07
21
757 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
Comment Utility
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
Comment Utility
glebspy,
In other words: Your T result in class A wouldn't be particularly useful.

Stefan
0
 
LVL 10

Expert Comment

by:Sys_Prog
Comment Utility
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
 
LVL 10

Expert Comment

by:Sys_Prog
Comment Utility
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
Comment Utility
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
Comment Utility
Sys_Prog,
Looks like we had the same idea - encouraging ;-)

Stefan
0
 
LVL 10

Expert Comment

by:Sys_Prog
Comment Utility
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
Comment Utility
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
Comment Utility
But Yeah, it was encouraging  :-)

Amit
0
 
LVL 10

Assisted Solution

by:Sys_Prog
Sys_Prog earned 200 total points
Comment Utility
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
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 48

Accepted Solution

by:
AlexFM earned 300 total points
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
Any other suggestion?
0
 
LVL 48

Expert Comment

by:AlexFM
Comment Utility
0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
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
Comment Utility
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
Comment Utility
>>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
Comment Utility
thanks axter
0
 
LVL 1

Author Comment

by:glebspy
Comment Utility
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

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Suggested Solutions

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…
Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a …
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
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.

763 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

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now