I have the following set of classes (a minimal replication of my real situation):
namespace Parent
{
class A {};
namespace Nested
{
class A {};
}
template <typename T>
class B
{
A myA;
};
}
I would expect that the member Parent::B::myA
should be unambiguously resolved to be of type Parent::A
. However, elsewhere in my project I have this:
namespace Parent
{
using namespace Nested;
void foo()
{
B<int> myB;
}
}
which fails to compile under MSVC 2003:
error C2872: 'A' : ambiguous symbol
could be 'Test.cpp(5) : Parent::A'
or 'Test.cpp(9) : Parent::Nested::A'
Test.cpp(26) : see reference to class template instantiation 'Parent::B<T>' being compiled
with [ T=int ]
The code will compile if I am explicit in my declaration of B::myA
, i.e. Parent::A myA;
. However, the code compiles as it is under gcc-4.3.4. Is this simply a bug with MSVC 2003, or should I really have to worry about the scope in which my templates may be instantiated?
The act of creating a new definition of a function, class, or member of a class from a template declaration and one or more template arguments is called template instantiation.
To instantiate a template class explicitly, follow the template keyword by a declaration (not definition) for the class, with the class identifier followed by the template arguments. template class Array<char>; template class String<19>; When you explicitly instantiate a class, all of its members are also instantiated.
Class template instantiationIn order for any code to appear, a template must be instantiated: the template arguments must be provided so that the compiler can generate an actual class (or function, from a function template).
All the template parameters are fixed+known at compile-time. If there are compiler errors due to template instantiation, they must be caught at compile-time!
It is a long standing bug in all versions of MSVC.
The problem is related to an incorrect implementation of name lookup in templates in MSVC.
Basically, MSVC will wait until the point of instantiation to perform name lookup, while the Standard is explicit that the correct behavior is to:
This behavior allows MSVC to be lax with regard to the use of typename
or template
, because it can fully deduce the symbols nature (differentiate regular variables from functions or types), however it's a nightmare when one aims at compatibility with other compilers.
If you can, ditch MSVC. If you can't... good luck.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With