Now it makes sense...
GCC is right, and MSVC is wrong. It should not work because a
is template dependent but the expression a;
is not.
That is, the meaning you intend of a
depends on a template argument (in your case K
), but the expression that contains it does not. And since the compiler cannot be sure that the instantiation of A<K>
will have a member named a
, it simple assumes it does not.
There are several easy solutions, all of them involve using a template dependent expression so resolve a
:
this->a = 3; //my favourite
A<K>::a = 3; //you found this one
EXAMPLE:
Let's see an example of why it should not work:
template <typename K> struct A
{
int a;
};
int a; //global variable to make things more interesting
template <typename K> struct B : A<K>
{
void foo()
{
a = 3; //does it refer to A<K>::a or ::a?
}
};
//template specialization of A<int>
template <> struct A<int>
{
};
B<float> bf; // what does bf.foo() do?
B<int> bi; //and bi.foo()?
Also, you can make the opposite situation:
template <typename K> struct A
{
};
int a; //global variable to make things more interesting
template <typename K> struct B : A<K>
{
void foo()
{
a = 3; //does it refer to A<K>::a or ::a?
}
};
//template specialization of A<int>
template <> struct A<int>
{
int a; //now the member variable is in the specialization
};
B<float> bf; // what does bf.foo() do?
B<int> bi; //and bi.foo()?
As you can see, the standard C++ behavior is there for you protection, so that the code you write in a template will always refer -more or less- to the same things:
a
: will be always the non template (global in the example) variable, if available. If not, it is a compiler error.
this->a
: will be always the member variable, if available. If not, a compiler error.