它是有效的C ++吗?
#include <iostream>
class Test {
struct Inner {
};
public:
using Inner = Inner; // Alias with same name as type
};
int main(int argc, const char * argv[]) {
static_assert(std::is_pod<Test::Inner>::value, "");
return 0;
}
使用clang编译良好,但不使用GCC / Visual C ++编译(“ Inner is private ...”错误消息)
GCC和Visual C ++是正确的。
事实上,您可以使用using
实际上更改成员的访问权限,例如
using Inner_ = Inner;
with
static_assert(std::is_pod<Test::Inner_>::value, "");
在函数中。
但是,如果类型别名与成员具有相同的名称,则C ++要求范围解析运算符查找该成员。因此,在您的情况下,Test::Inner
是指实际成员而不是using
,因此编译应该会失败,因为它是private
。
请参见https://en.cppreference.com/w/cpp/language/qualified_lookup,尤其是
在命名空间N范围内的合格查找首先考虑了所有位于N中的声明和所有位于位于N的内联名称空间成员中(以及,在他们的内联名称空间成员)。如果那没有声明设置,然后考虑由命名的所有命名空间中的声明在N和所有可传递内联命名空间中找到的using指令N个成员
[我认为目前标准无法回答谁是正确的,P1787R4: Declarations and where to find them似乎偏爱GCC和MSVC行为:
附加段落:
在某些情况下,仅包括某些种类的声明。在进行任何此类限制之后,如果找到任何其他声明,则将丢弃任何类或枚举的声明。 [注意:因此,类型(但不是typedef名称或模板)在其范围内被任何其他实体隐藏。 — —尾注]但是,如果查找是仅类型的,则仅考虑类型和类型专门针对类型的模板的声明; 此外,如果找到
typedef
声明符及其引用类型的声明,则将typedef
声明符代替类型声明而丢弃。