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;
Related
I think the best way to explain what i want to accomplish will be through code:
template<typename T>
struct Foo {
static void func(Bar<T> obj);
}; // ^ syntax error: identifier 'Bar'
template<typename T>
struct Bar {
T data;
};
To resolve this, you just need what's called a "forward declaration":
template<typename T>
struct Bar;
template<typename T>
struct Foo {
static void func(Bar<T> obj); //syntax error no more
};
template<typename T>
struct Bar {
T data;
};
At the point where Bar<T> is referenced first the compiler does not have any idea what it is. You just need to add a declaration, beforehand, and the full definition of the template can still appear later.
The following code compiles.
matrix.h before template
template<typename T>
class Matrix
{
public:
//...
unique_ptr<Matrix<T>> Test() const;
};
matrix.cpp before template
template<typename T>
unique_ptr<Matrix<T>> Matrix<T>::Test() const
{
unique_ptr<Matrix<T>> a{ new Matrix<T>{ 1, 1 } };
return std::move(a);
}
I wanted to use a typedef (using) to shorten things as I thought it'd be more readable but my changes cause errors. Here are the relevant changes.
matrix.h after template
template<typename T>
class Matrix
{
public:
//...
MatrixUniq<T> Test() const;
};
template<class T> using MatrixUniq = unique_ptr<Matrix<T>>;
matrix.cpp after template
template<typename T>
MatrixUniq<T> Matrix<T>::Test() const
{
MatrixUniq<T> a{ new Matrix<T>{ 1, 1 } };
return std::move(a);
}
Compiling after these changes are made crashes the VC++ compiler twice, but also generates a few errors:
Error C2143 syntax error: missing ';' before '<'
Error C4430 missing type specifier - int assumed.
Error C2238 unexpected token(s) preceding ';'
Error C1903 unable to recover from previous error(s);
What's wrong with my typedef implementation? Thanks.
Edit:
I'm using VS2015. I'm building a static library. At the bottom of matrix.cpp I have:
template class VMatrix<double>;
You are using the MatrixUniq<T> alias before having defined it.
Move the using inside the class:
template<typename T>
class Matrix
{
public:
template<class U> using MatrixUniq = std::unique_ptr<Matrix<U>>;
MatrixUniq<T> Test() const;
};
And change the definition accordingly:
template<typename T>
Matrix<T>::MatrixUniq<T> Matrix<T>::Test() const
{
return MatrixUniq<T>{ new Matrix<T>{ 1, 1 } };
}
Or if you want to have it in the global namespace, define it before the class definition after a forward declaration on the class:
template<typename T>
class Matrix;
template<class T> using MatrixUniq = std::unique_ptr<Matrix<T>>;
template<typename T>
class Matrix
{
public:
//...
MatrixUniq<T> Test() const;
};
Also you don't need to explicitly do a std::move when returning local variables. Local variables that are returned are automatically moved by default.
try this:
template<typename T>
class Matrix
{
public:
using unique_ptr_type = std::unique_ptr<Matrix>;
//...
unique_ptr_type Test() const;
};
template<class T> using MatrixUniq = typename Matrix<T>::unique_ptr_type;
template<typename T>
typename Matrix<T>::unique_ptr_type Matrix<T>::Test() const
{
return unique_ptr_type(new Matrix());
}
Always make sure to declare templates above the code which will be using it.
Also this snippet:
template<class T> using MatrixUniq = unique_ptr<Matrix<T>>;
might not be a correct implementation.
Here's how you can declare a type definition in c++.
typedef <type> <var_name>
Here's another example using an 'Alias Template'
template<typename T>
using MyVector = std::vector<T, MyCustomAllocator<T>>;
The rest of the code is for you to debug.
See this relevant discussion here:
How to typedef a template class?
Please help me I don't know what happens. It shows
error C2955: 'MyClass' : use of class template requires template argument list
template <class T> class MyClass
{
protected:
struct MyStruct
{
};
MyStruct* GetElement(...) const;
}
//error C2955: 'MyClass' : use of class template requires template argument list
//I tried:
// MyClass<T>::MyStruct* MyClass<T>::GetElement(...) const
// MyStruct* MyClass<T>::GetElement(...) const
// but none works. This method doesn't use T.
template<class T>
MyClass::MyStruct* MyClass<T>::GetElement(...) const
{
}
These fixes work
template <class T> class MyClass {
protected:
struct MyStruct
{
};
MyStruct* GetElement(...) const;
}; // << add semicolon
template <class T>
// Add typename
typename MyClass<T>::MyStruct* MyClass<T>::GetElement(...) const {
// Add <T> ^^^
return NULL;
}
Any type that depends on the template parameter must be specified with typename.
The return type of GetElement should be written as typename MyClass<T>::MyStruct*:
template<class T>
typename MyClass<T>::MyStruct* MyClass<T>::GetElement(...) const
{
}
The <T> is necessary because MyClass is a template class. typename is needed because MyClass<T>::MyStruct is a dependent name.
I have a class called node inside another class which is templated. Some of the methods of class Node returns Node pointer. This is an excerpt of how I implemented
template <typename T>
class myClass{
....
class Node{
Node* getNodePointer();
...
}
}
...
template <typename T>
myClass<T>::Node* myClass<T>::Node::getNext()
{ return next; }
When I compile above code, I get this error " myClass.h:138:1: error: need ‘typename’ before ‘myClass::Node’ because ‘myClass’ is a dependent scope". How do I fix this problem? Many thanks
To clarify, the compiler has no idea that myClass<T>::Node is now or ever will be a type. Think of it this way:
template <typename T>
class A
{
public:
typedef T value_type;
};
template <typename T>
class B
{
public:
typename A<T>::value_type x;
};
template <> A<int> { public: static int value_type=10;}
You have to make the promise to the compiler that the type is a typename. It defaults to assuming that it is a value.
How do I fix this problem?
The compiler's error message s pretty clear about this point:
To use nested classes, structs or typedefinitions from a template class you need to add the typename keyword to tell the compiler you want to use it as a type:
template <typename T>
typename myClass<T>::Node* myClass<T>::Node::getNext() { // ...
// ^^^^^^^^ << Add typename keyword
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.