I used a simple class for a test program about templates, this is what I did:
template <typename T>
class test
{
public:
test<T>::test();
T out();
};
template <typename T>
test<T>::test()
{
}
T test<T>::out()
{
}
int main()
{
//test<int> t;
}
But when I try to compile it says 'T' : undeclared identifier and use of class template requires template argument list , pointing to the same line, where I have implemented the method out() . Can anyone please explain what the problem is?? I'm using visual studio 2008.
Following is more accurate:
template <typename T>
class test
{
public:
test();
T out();
};
template <typename T>
test<T>::test()
{
}
template <typename T>
T test<T>::out()
{
}
1) Don't use <T> inside class
2) Don't forget to declare template <T> before each method declaration out of class body
This line is wrong:
test<T>::test();
Just write this:
test();
Your definition of the out member is missing the template argument list. out should read:-
template <typename T>
T test<T>::out()
{
}
Related
I just updated to GCC 4.8.2 (from 4.7), and am now getting a warning for the following code:
template <class T_base>
class factory {
private:
template <class T>
struct allocator : factory {
// ^ warning: invalid use of incomplete type 'class factory<T_base>'
};
};
To avoid the warning, I tried to define struct allocator outside of factory, but now get the following error:
template <class T_base>
class factory {
private:
template <class T>
struct allocator;
};
template <class T_base, class T>
struct factory<T_base>::allocator<T> : factory<T_base> {
// ^ error: too few template-parameter-lists
};
What am I doing wrong? Is there a syntax for the above construct that avoids both the warning and the error?
You need to spell it like this:
template <class T_base>
template <class T>
struct factory<T_base>::allocator : factory<T_base>
{
// ...
};
The correct syntax for declaring a nested template is to have two separate template argument lists:
template <class T_base>
template <class T>
struct factory<T_base>::allocator : factory<T_base> {
};
However, I’m questioning which semantic sense this piece of code makes.
I am facing a problem with templated member function pointer.
The code is as shown below.
#include <String>
#include <iostream>
template<typename T>
struct method_ptr
{
typedef void (T::*Function)(std::string&);
};
template <class T>
class EventHandler
{
private:
method_ptr<T>::Function m_PtrToCapturer;
};
e:\EventHandler.h(13) : error C2146: syntax error : missing ';' before identifier 'm_PtrToCapturer'
I am facing this error.
Even If I use
method_ptr<EventHandler>::Function m_PtrToCapturer;
as member variable I am getting same error as above.
Because method_ptr<T>::Function is a dependent name (dependent on T), you need to disambiguate it with typename:
template <class T>
class EventHandler
{
private:
typename method_ptr<T>::Function m_PtrToCapturer;
// ^^^^^^^^
};
This works,
struct method_ptr
{
typedef void (T::*Function)(std::string&);
};
template <class T>
class EventHandler
{
private:
typename method_ptr<T>::Function m_PtrToCapturer;
};
Since C++11, you can use using.
template <typename T>
using Function = void (T::*)(std::string);
(By the way, why is std::string called-by-value? I recommend const std::string &.)
Aha, I figured out your second question.
template <typename T>
method_ptr<T>::Function m_PtrToMemFunc; //<--
template is only applied to class and function (and cpp11's typedef&using...). you should write like this.
method_ptr<SomeClass>::Function m_PtrToMemFunc;
This is code i have written to understand the concept. The code is fine and it runs.
What i dont understand is that why is the marked line needed ?
template <class T>
class D
{
public :
template <class P> //<------------------Why is this needed ? --------------
friend void print(D <P> obj);
};
template <class T>
void print(D<T> obj)
{std::cout<<sizeof(T);};
int main()
{
D <char>obj3;
print(obj3);
return 0;
}
or in other words why does the following not run ?
template <class T>
class D
{
public :
friend void print(D <T> obj);
};
As per [temp.friend], you must provide explicit template arguments to make a specialisation of a template function a friend:
template <class T>
class D
{
public :
friend void print<T>(D <T> obj);
};
Without it, the compiler will be looking for a function print(), not a function template print().
I'm writing an array class. This array class can contain again arrays as members. When implementing a printing function, I need specializations.
26:template <class T> class array : public vector<T>{
public:
...
string* printToString();
...
};
...
template <class T> string* array<T>::printToString(){
... // generic function
}
template <> inline string* array<double>::printToString(){
... // spezialization for double, works
}
561:template <class U> string* array<array<U>*>::printToString(){
... // does not work
}
The last definition produces
src/core/array.h:561: error: invalid use of incomplete type ‘class array<array<T> >’
src/core/array.h:26: error: declaration of ‘class array<array<T> >’
The g++ version is g++ (Ubuntu 4.4.3-4ubuntu5) 4.4.3 if that matters.
Any ideas what's the problem?
Thanks in advance,
Thomas
As an alternative to David's solution, you can unconditionally forward the call to a set of overloaded functions:
template <class T> class array;
namespace details {
template <class T> std::string array_print(array<T> const&);
std::string array_print(array<double> const&); // Regular function
template <class T> std::string array_print(array<array<T> > const&);
}
template <class T> class array : private vector<T> {
public:
...
std::string printToString() { return details::array_print(*this); }
...
};
namespace details { /* implementions after class is defined */ }
You cannot partially specialize a function, you can only fully specialize it, which is the reason why you can provide an specialization for double but not for array<U> where U is a generic type.
You can get around this limitation by using a class template, and partially specializing that, but it will be a bit cumbersome.
namespace detail {
template <typename T>
struct array_printer {
static std::string print( array<T> const & array ) {
// basic implementation
}
};
template <typename T>
struct array_printer< array<T> > {
static std::string print( array< array<T> > const & array ) {
// specialization for array<T>
}
}
}
And then implement the member function as a simple dispatch to the appropriate overload:
template <typename T>
class array : std::vector<T> { // do not publicly derive from STL containers
public:
std::string printToString() const {
return detail::array_printer<T>::print( *this );
}
}
Of course, things are a little more complex in real code, and you will have to order the code appropriatedly, and provide forward declarations of the templates and all that, but this should be enough to get you started.
Your function must be fully specialized. For example:
// Fully specialized. You cannot replace `double` with generic parameter.
template <>
string* array<array<double>*>::printToString(){
return nullptr;
}
However, your class can be partially specialized. For example:
template <class T> class array : public vector<T>{
public:
string* printToString();
};
template <class T> string* array<T>::printToString(){
return nullptr;
};
// Partial specialization.
template <class T> class array<array<T>*> : public vector<T>{
public:
string* printToString();
};
template <class T> string* array<array<T>*>::printToString(){
return nullptr;
};
-- EDIT ---
The methods from generic class will not be automatically "taken" by the class specialization, or vice-versa. You can, however use inheritance to "automate" the reuse of methods from generic class. For example...
template <class T> class array : public vector<T>{
public:
string* printToString();
void f();
};
// (1a)
template <class T> string* array<T>::printToString(){
return nullptr;
};
// (2)
template <class T> void array<T>::f(){
};
template <class T> class array<array<T>*> : public array<T> {
public:
string* printToString();
};
// (1b)
template <class T> string* array<array<T>*>::printToString(){
return nullptr;
};
void Test() {
array<double> a1;
a1.printToString(); // Calls (1a).
a1.f(); // Calls (2).
array<array<char>*> a2;
a2.printToString(); // Calls (1b).
a2.f(); // Calls (2).
}
...which may or may not be what you need (some "manual" repetition might be necessary).
template <class T>
class Test
{
public:
template<class T>
void f(); //If i define function here itself, error is not reported.
};
template <class T>
void Test<T>::f()
{
} //Error here.
int main()
{
Test<float> ob;
ob.f<int>();
}
It produces below error.
error C2244: 'Test<T>::f' : unable to match function definition to an
existing declaration
definition 'void Test::f(void)'
existing declarations 'void Test::f(void)'
Error says declaration and definitions have the same prototype but not matching.
Why is this an error ? and how to solve it ?
If i define function within the class, it doesn't report error.
But i want to define outside the class.
Change as
template <class T>
class Test
{
public:
template<class U>
void f();
};
template <class T>
template<class U>
void Test<T>::f()
{
}
....
public:
template<class T> // this shadows the previous declaration of typename T
void f();
};
Change the parameter name. Here is the working code.