Рассмотрим следующий код:
#include <cstddef>
class A
{
public:
struct B
{
int M;
};
static void StaticFunc();
};
void A::StaticFunc()
{
const std::size_t s0 = sizeof(::A::B::M);
const std::size_t s1 = sizeof(A::B::M);
const std::size_t s2 = sizeof(B::M);
}
int main()
{
const std::size_t s3 = sizeof(A::B::M);
return 0;
}
GCC компилирует это, просто предупреждение о неиспользованных переменных.
Однако Visual C ++ 2015 не может скомпилировать его:
error C2326: 'void A::StaticFunc(void)': function cannot access 'A::B::M'
на линии
const std::size_t s0 = sizeof(::A::B::M);
const std::size_t s1 = sizeof(A::B::M);
в StaticFunc()
,
Другая линия s2 = ...
, а также s3 = ...
в main()
компилировать нормально.
Это ошибка в MSVC, или я здесь что-то упускаю?
Это ошибка в MSVC.
C ++ 11/14 позволяет использовать нестатический член класса в не оцененном контексте, см. 5.1.1 [expr.prim.general] p. 13:
Выражение id, которое обозначает нестатический член данных или нестатическую функцию-член класса, может использоваться только:
…
(13.3) — если это id-выражение обозначает нестатический элемент данных и появляется в неоцененном операнде.
[ Пример:struct S { int m; }; int i = sizeof(S::m); // OK int j = sizeof(S::m + 42); // OK
— конец примера]
Изменить: похоже, что MSVC принимает B::M
и не принимает A::B::M
, что является совершенно необъяснимым поведением. Я не понимаю, как это может быть что-то кроме ошибки.
clang ++, как g ++ в режиме C ++ 11 и C ++ 14, принимает программу. clang ++ в режиме C ++ 03 отклоняет все 4 ссылки на M
(C ++ 03 не имеет ничего похожего на стр. 13.3), тогда как g ++ в режиме C ++ 03 по-прежнему принимает их (это, вероятно, ошибка режима g ++ C ++ 03).
Других решений пока нет …