Могу ли я объявить псевдоним типа члена для типа в окружающей области, используя то же имя?

Я хочу, чтобы структура содержала псевдоним типа для другого типа в целях метапрограммирования:

struct Foo {};

struct WithNestedTypeAlias {
using Foo = Foo;
};

Тогда я могу делать такие вещи, как WithNestedTypeAlias::Foo в шаблоне и т. д.

Как я понимаю, этот псевдоним типа действителен, потому что он не меняет смысла Foo тип. Clang компилирует это счастливо.

Однако GCC жалуется:

test-shadow-alias.cpp:4:20: error: declaration of ‘using Foo = struct Foo’ [-fpermissive]
using Foo = Foo;
^
test-shadow-alias.cpp:1:8: error: changes meaning of ‘Foo’ from ‘struct Foo’ [-fpermissive]
struct Foo {};
^

Теперь я в замешательстве, потому что я явно не меняю значение Foo от struct Foo,

Каково правильное поведение для C ++ 14? Я знаю, что могу обойти это, переименовав struct Foo, но я хотел бы понять, является ли ошибка GCC здесь правильной.

Заметки:

8

Решение

Правило, которое GCC применяет, находится в [basic.scope.class]:

2) Имя N, используемое в классе S, должно относиться к тому же объявлению в его контексте и при повторной оценке в завершенной области S. Не требуется никакой диагностики для нарушения этого правила.

Стандарт гласит, что нарушение этого не требует диагностики, поэтому возможно, что и GCC, и Clang соответствуют, потому что (если GCC верен) код недействителен, но компилятор не обязан его диагностировать.

Цель этого правила состоит в том, что имена, используемые в классе, всегда означают одно и то же, и изменение порядка членов не влияет на их интерпретацию, например.

struct N { };

struct S {
int array[sizeof(N)];

struct N { char buf[100]; };
};

В этом примере имя N меняет значение, и переупорядочение членов изменит размер S::array, когда S::array определено N относится к типу ::N но в завершенном объеме S это относится к S::N вместо. Это нарушает правило, указанное выше.

В вашем примере имя Foo изменения гораздо менее опасным образом, потому что он по-прежнему относится к тому же типу, однако, строго говоря, он действительно отличается от обращения к объявлению ::Foo к декларации S::Foo, Правило сформулировано в терминах ссылки на декларации, поэтому я считаю, что GCC прав.

7

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]