Fun with templates

Started by
7 comments, last by nikdo 18 years, 9 months ago
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 ==================================================================
If you aren't diving, you ain't living
Advertisement
hi

template <int, typename T>

should be

template <int I, typename T>
“Always programm as if the person who will be maintaining your program is a violent psychopath that knows where you live”
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


If you aren't diving, you ain't living
typename std::multimap<Uint, QueueMessage<TObject>* >::iterator isQueued(Uint msgId);
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!
If you aren't diving, you ain't living
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);
“Always programm as if the person who will be maintaining your program is a violent psychopath that knows where you live”
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
If you aren't diving, you ain't living
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.
SiCrane,

thank you sincerely for taking the time today to respond to my questions. I understand now completely and appreciate your help.

I'm about to delve into "Modern C++ Design" by Andrei Alexandrescu, a fantastic book all about templates (and much more of course). Wish me luck!

Peter
If you aren't diving, you ain't living

This topic is closed to new replies.

Advertisement