Сокрытие имен c помощью type alias
Пример:
struct A {};
struct B { using A = A; };
int main()
{
B b;
}
Clang компилирует это. GCC выдает ошибку (пример):
declaration of 'using A = struct A' changes meaning of 'A'
В стандарте написано:
If a class name ([class.name]) or enumeration name ([dcl.enum]) and a variable, data member, function, or enumerator are declared in the same declarative region (in any order) with the same name (excluding declarations made visible via using-directives ([basic.lookup.unqual])), the class or enumeration name is hidden wherever the variable, data member, function, or enumerator name is visible.
P.S. Спасибо Vlad From Moscow
A name N used in a class S shall refer to the same declaration in its context and when re-evaluated in the completed scope of S. No diagnostic is required for a violation of this rule
Получается, у GCC - некорректное поведение?
Ответы (1 шт):
Синтаксис using A = A; это красивый синтаксис для команды typedef. Она позволяет использовать синоним типа в другом пространстве имён. Это аналог :
struct B {
typedef A A ;
} ;
Правила не позволяют переопределять типы, уже созданные в данном пространстве класса или структуры.
Стандарт :
In a given non-class scope, a typedef specifier can be used to redefine the name of any type declared in that scope to refer to the type to which it already refers. [ Example:
typedef struct s { /∗ ... ∗/ } s;
typedef int I;
typedef int I;
typedef I I; // OK
In a given class scope, a typedef specifier can be used to redefine any class-name declared in that scope that is not also a typedef-name to refer to the type to which it already refers. [ Example:
struct S {
typedef struct A { } A; // OK
typedef struct B B; // OK
typedef A A; // error
};
Компилятор так и намекает вам про ошибку :
error: declaration of ‘typedef struct A B::A’ changes meaning of ‘A’ [-fpermissive]
То есть нельзя внутри структуры B тип A называть типом A ( структуры B ).
Подсказка: чтобы подправить разное поведение компиляторов, using можно использовать указывая из какого пространства имён вы хотите взять синоним :
struct A {};
struct B {
using A = :: A ;
} ;
Я думаю, что в GCC ошибка. Так как новый синоним типа B :: A ещё не создан, а typedef уже говорит, что он есть.
Стандарт :
In particular, it does not define a new type and it shall not appear in the type-id.
using cell = pair<void*, cell*>; // ill-formed