Click to See Complete Forum and Search --> : Template, namespace, and friend problem
abcd_68
January 13th, 2005, 12:52 PM
Hi,
the following code snippet compiles (and runs) fine on g++ 3.3.4 but yields C2888 (symbol cannot be defined within namespace) under VC++ .net (7.0.9466).
#include "Factory.h"
using Framework::Factory;
using Framework::Gate;
namespace Application {
class MyClass {
//...
template<typename T> friend class Factory; //C2888
friend class Gate; //Ok
//...
};
}
Please note that:
1. everything compiles fine if I remove the Application namespace i.e., if I declare MyClass in the global namespace
2. it also works fine if I put MyClass into the same namespace as Factory (i.e., the Framework namespace). Apparently the compiler is unable to see that Factory *was* indeed defined in Factory.h, and that here I'm just declaring it as a friend
3. Gate, a non-template class from the same namespace as Factory, compiles Ok
4. as said above, everything's fine under g++ so there cannot be any obvious problems with any class (particularly with Factory).
Any ideas?
Thanks a lot in advance
Andy
NoHero
January 13th, 2005, 12:57 PM
the following code snippet compiles (and runs) fine on g++ 3.3.4 but yields C2888 (symbol cannot be defined within namespace) under VC++ .net
C2888 (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore/html/C2888.asp)
abcd_68
January 13th, 2005, 01:05 PM
Yes I know what the MSDN says about that error, but still I don't see the reason why it is emitted. I'm not defining Factory here, I'm just declaring it as a friend. And why only for templates? And why not on g++?
NoHero
January 13th, 2005, 01:12 PM
You should also check the code. This means that the namespace where this class is in does not enclose the namespace where the template Factory() is in.
The example provided by MSDN is the same thing you have, I just flip the names of the namespaces:
// C2888.cpp
namespace Framework
{
namespace Factory
{
void f1();
void f2();
}
void Factory::f1()
{ //OK: namespace Framework encloses Factory
}
}
namespace Application
{
void Framework::Factory::f2()
{ // C2888: namespace Application does not enclose Framework
}
}
It's hard for me to explain what you have done wrong.
But take a look twice at this example provided here.
If you want to declare a class as a friend it must be in the
same namespace as the class which you declare it in. You may
not grant access to a class that does not belong to the same namespace.
I have never seen this error before, and I do not know exactly what
behaviour is ANSI standard and which isn't.
MrViggy
January 13th, 2005, 01:39 PM
Have you tried:
#include "Factory.h"
using Framework::Factory;
using Framework::Gate;
namespace Application {
class MyClass {
//...
template<typename T> friend class Framework::Factory; //C2888
friend class Gate; //Ok
//...
};
}
Viggy
abcd_68
January 13th, 2005, 02:15 PM
MyViggy: Sure, it's the first workaround I tried. Same error.
NoHero: I see your point but still I'm not convinced. Whatever the standard says about it, the fact that the error is only triggered by a template doesn't make sense, and has nothing to do with the explanation contained in the MSDN, which does not mention templates. Also, recall that Gate does work, even if it is in the very same situation as Factory as far as namespaces are concerned.
I tend to blame the problem on the way VC++ treats templates. Maybe, for some reason, the compiler is not able to istantiate the template correctly, but this is only a guess. In any case, it's got to be a problem that involves both namespaces and templates.
Paul McKenzie
January 13th, 2005, 03:04 PM
Please post a complete (i.e. what is factory.h?), but small sample of your code that duplicates the problem. Then others can try the code on various compilers to see what errors come up.
(I seem to be saying this more and more these days).
Regards,
Paul McKenzie
MrViggy
January 13th, 2005, 03:23 PM
Ditto to what Paul said. Also, can you post the actual error message. The full error message is:
'identifier' : symbol cannot be defined within namespace 'namespace'
However, your original post did not tell us (a) what 'identifier' the compiler was complaining about, and (b) what 'namespace' the compiler was complaining about.
Viggy
abcd_68
January 13th, 2005, 03:42 PM
(I seem to be saying this more and more these days).
Sorry, I'm entirely new to this forum (I subscribed a couple of hours ago).
Anyway, here it comes. This is the smallest example I could think of (empty classes!). Again, it compiles (and links, and runs) just fine under g++ 3.3.4 with -W -Wall -ansi -pedantic
//Framework.h
namespace Framework {
template<typename T> class Factory {};
class Gate {};
}
//Application.cpp
#include "Framework.h"
using Framework::Factory;
using Framework::Gate;
namespace Application {
class App {
template<typename T> friend class Factory; //C2888
friend class Gate; //Ok
};
}
int main() {}
Can anyone help?
Thanks again,
Andy
abcd_68
January 13th, 2005, 03:45 PM
The full message is:
error C2888: 'Framework::Factory' : symbol cannot be defined within namespace 'Application'
MrViggy
January 13th, 2005, 04:00 PM
Removing the "template <...>" seems to fix the compile error. However, I don't know if this has the desired effect...
#include "Framework.h"
using Framework::Factory;
using Framework::Gate;
namespace Application {
class App {
friend class Factory; //Ok
friend class Gate; //Ok
};
}
Viggy
Paul McKenzie
January 13th, 2005, 04:26 PM
I tried the following:
namespace Framework {
template<typename T> class Factory {};
class Gate {};
}
using Framework::Factory;
using Framework::Gate;
namespace Application {
class App {
template<typename T> friend class Factory; //C2888
friend class Gate; //Ok
};
}
int main() {}
Your code compiles cleanly using the Comeau C++ compiler (one of the most ANSI compliant compilers out there). This is a good indication that there is nothing wrong with your code, and you just have to come up with a workaround for broken compilers.
Regards,
Paul McKenzie
abcd_68
January 13th, 2005, 04:49 PM
Removing the "template <...>" seems to fix the compile error. However, I don't know if this has the desired effect...
Thanks Viggy and Paul,
looks like I'll have to maintain two different versions, one for VC++ and one for g++ as Viggy's workaround actually works under VC++ but not under g++ which is certainly more ANSI compliant than VC++.
So I'll have to use the last resort i.e., the ugly #ifdef directive :-(
Thanks very much,
Andy
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.