Fun with templates
Hello everyone,
I am a bit stumped with the errors I get from the compiler VC++ 8.0. Anyone can point out my errors?
I am basically trying to have a templated object as a return type, and that is causing me problems.
Note: this is just an example code, not an actual one.
TIA, Peter
==================================================================
template<typename T>
class EntityItems
{
public:
T items[];
};
template<int, typename T>
class MonsterEntity
{
public:
T items;
int _count;
};
template<typename T>
class MonsterEntityManager
{
public:
MonsterEntity<int, EntityItems<T> &> Exists(int itemKey);
};
Compiler error:
Error 4 error C2975: 'Core::MonsterEntity' : invalid template argument for 'unnamed-parameter', expected compile-time constant expression
==================================================================
Dragongame, thanks for the reply.
I think that my example was oversimplified. I tried to create a small example, taking out the complexities of my own design.
In any case, here is my real classes, and the error:
======================================================================
template<typename TObject>
struct QueueMessage
{
const Message<TObject>& Msg; // The message to queue.
const MessageHandlerList<TObject>& HandlerList; // The looked-up HandlerList.
/// Cctor
QueueMessage(const Message<TObject>& msg, MessageHandlerList<TObject>& hndlrList) : Msg(msg), HandlerList(hndlrList){};
/// Destructor
~QueueMessage()
{
delete Msg;
};
};
template<typename TObject>
class MessageManager
{
private:
MessageManager();
protected:
const Core::Entity& _owner;
stdext::hash_map<Uint, MessageEntry<TObject>* > _msgRegistry;
std::multimap<Uint, QueueMessage<TObject>* > _queue;
public:
MessageManager(const Core::Entity<TObject>& owner);
~MessageManager();
std::multimap<Uint, QueueMessage<TObject>* >::iterator isQueued(Uint msgId);
};
The last line fails to compile (no definition for it in .cpp yet) with the following errors:
error C2146: syntax error : missing ';' before identifier 'isQueued'
error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
So obviously, it doesn't understand the return type. I know the problem is the nested template, the QueueMessage<TObject>, because if I replace that one with any class that doesn't need a template or a basic data type, it compiles.
Furthermore, I have created an iterator the same exact way, to the letter, in other member function definitions of the same class (in the body of the member function) and it worked. It's only when I use it as a return type that I have a problem.
Any ideas guys?
Thank you very much!
Peter
I think that my example was oversimplified. I tried to create a small example, taking out the complexities of my own design.
In any case, here is my real classes, and the error:
======================================================================
template<typename TObject>
struct QueueMessage
{
const Message<TObject>& Msg; // The message to queue.
const MessageHandlerList<TObject>& HandlerList; // The looked-up HandlerList.
/// Cctor
QueueMessage(const Message<TObject>& msg, MessageHandlerList<TObject>& hndlrList) : Msg(msg), HandlerList(hndlrList){};
/// Destructor
~QueueMessage()
{
delete Msg;
};
};
template<typename TObject>
class MessageManager
{
private:
MessageManager();
protected:
const Core::Entity& _owner;
stdext::hash_map<Uint, MessageEntry<TObject>* > _msgRegistry;
std::multimap<Uint, QueueMessage<TObject>* > _queue;
public:
MessageManager(const Core::Entity<TObject>& owner);
~MessageManager();
std::multimap<Uint, QueueMessage<TObject>* >::iterator isQueued(Uint msgId);
};
The last line fails to compile (no definition for it in .cpp yet) with the following errors:
error C2146: syntax error : missing ';' before identifier 'isQueued'
error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
So obviously, it doesn't understand the return type. I know the problem is the nested template, the QueueMessage<TObject>, because if I replace that one with any class that doesn't need a template or a basic data type, it compiles.
Furthermore, I have created an iterator the same exact way, to the letter, in other member function definitions of the same class (in the body of the member function) and it worked. It's only when I use it as a return type that I have a problem.
Any ideas guys?
Thank you very much!
Peter
Sicrane, thanks a bunch!
I've been hitting my head into the wall for quite a while now, being new to templates and all. I have seen in my books that you're supposed to use typename when the compiler cannot resolve what exactly the template instantiation represents, as in:
template<class Parm, class U>
Parm minus(Parm* array, U value)
{
Parm::name * p; // Is this a pointer declaration or a multiplication?
// It is actually a multiplication.
}
template<class Parm, class U>
Parm minus(Parm* array, U value)
{
typename Parm::name * p; // Ok now, pointer declaration.
}
However I don't see exactly what got the compiler confused with the
std::multimap<Uint, QueueMessage<TObject>* >::iterator isQueued(Uint msgId);
line?
Would you, or someone else explain? And how come I only need to precise with typename for the return type, but not when declaring an iterator the same exact way in a body of a member function?
example:
std::multimap<Uint, QueueMessage<TObject>* >::iterator iter = this->_queue.find(msgId); // This works
Thanks!
I've been hitting my head into the wall for quite a while now, being new to templates and all. I have seen in my books that you're supposed to use typename when the compiler cannot resolve what exactly the template instantiation represents, as in:
template<class Parm, class U>
Parm minus(Parm* array, U value)
{
Parm::name * p; // Is this a pointer declaration or a multiplication?
// It is actually a multiplication.
}
template<class Parm, class U>
Parm minus(Parm* array, U value)
{
typename Parm::name * p; // Ok now, pointer declaration.
}
However I don't see exactly what got the compiler confused with the
std::multimap<Uint, QueueMessage<TObject>* >::iterator isQueued(Uint msgId);
line?
Would you, or someone else explain? And how come I only need to precise with typename for the return type, but not when declaring an iterator the same exact way in a body of a member function?
example:
std::multimap<Uint, QueueMessage<TObject>* >::iterator iter = this->_queue.find(msgId); // This works
Thanks!
Quote:Original post by nikdo
However I don't see exactly what got the compiler confused with the
std::multimap<Uint, QueueMessage<TObject>* >::iterator isQueued(Uint msgId);
line?
std::multimap<Uint, QueueMessage<TObject>* >::iterator iter = this->_queue.find(msgId); // This works
Thanks!
what happens when you remove the second Uint, like so:
std::multimap<Uint, QueueMessage<TObject>* >::iterator isQueued(msgId);
DragonGame,
std::multimap<Uint, QueueMessage<TObject>* >::iterator isQueued(msgId);
simply won't compile, since msgId is not a type defined anywhere, but rather a parameter name. The compiler doesn't know what to do with that. As a matter of fact parameter names are totally optional in function / method declarations.
As a matter of fact most people don't write parameter names in the declarations; I do because I find it more descriptive.
Hence the following can be written:
std::multimap<Uint, QueueMessage<TObject>* >::iterator isQueued(Uint);
In any case, I don't know if you noticed or not, but Sicrane's solution of putting "typename" in front of the line worked. I am just wondering why the typename was required.
Peter
std::multimap<Uint, QueueMessage<TObject>* >::iterator isQueued(msgId);
simply won't compile, since msgId is not a type defined anywhere, but rather a parameter name. The compiler doesn't know what to do with that. As a matter of fact parameter names are totally optional in function / method declarations.
As a matter of fact most people don't write parameter names in the declarations; I do because I find it more descriptive.
Hence the following can be written:
std::multimap<Uint, QueueMessage<TObject>* >::iterator isQueued(Uint);
In any case, I don't know if you noticed or not, but Sicrane's solution of putting "typename" in front of the line worked. I am just wondering why the typename was required.
Peter
You need to use typename whenever you use :: to get at a type depedent on a template parameter. In this example TObject is your template parameter, so
QueueMessage<TObject> is a type depedent on a template parameter. And since std::multimap<Uint, QueueMessage<TObject> *> depends on the type QueueMessage<TObject> then std::multimap<Uint, QueueMessage<TObject> *> is dependent on a template type paramter. And then you use :: to get at std::multimap<Uint, QueueMessage<TObject> *>'s iterator, you need to use typename in front of std::multimap<Uint, QueueMessage<TObject> *> in order for the :: to find iterator as a type.
QueueMessage<TObject> is a type depedent on a template parameter. And since std::multimap<Uint, QueueMessage<TObject> *> depends on the type QueueMessage<TObject> then std::multimap<Uint, QueueMessage<TObject> *> is dependent on a template type paramter. And then you use :: to get at std::multimap<Uint, QueueMessage<TObject> *>'s iterator, you need to use typename in front of std::multimap<Uint, QueueMessage<TObject> *> in order for the :: to find iterator as a type.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement