I have templated class that includes two nested class like below
#include <iostream>
template<typename A>
class c
{
class a
{
protected:
int i = 0;
};
class b: public a
{
public:
void print()
{
std::cout << "i of a: " << i; // fails
//std::cout << "i of a: " << this->i; // works
}
};
};
This gives compliation error: use of undeclared identifier 'i'
. I would expect the failure to relate to class a being dependent on the template parameter, but it does not seem to be the case here since a is not dependent on A.
I tried reading about dependent names in templates, but I am still unsure why this error occurs. Could someone explain the theoretical reason for this behavior?
Surprisingly this compiles without issues on MSVC but not in GCC and Clang. Any insights on why GCC/Clang behave differently from MSVC here would be greatly appreciated!
4
since
a
is not dependent onA
It is. You can specialize a
.
#include <iostream>
template<typename A>
class c
{
public:
class a
{
protected:
int i = 0;
};
class b: public a
{
public:
void print()
{
std::cout << "i of a: " << this->i;
}
};
};
template <>
class c<int>::a
{
// No `i`!
};
int main()
{
c<int>::b x;
x.print();
}
<source>:18:46: error: no member named 'i' in 'c<int>::b'
18 | std::cout << "i of a: " << this->i; // works
| ~~~~ ^
Surprisingly this compiles without issues on MSVC
You didn’t enable the standard conformance mode. All modern compilers will accept some invalid C++ by default.
It starts rejecting your code with /std:c++latest
or with /permissive-
.
2