类型别名与类型同名

问题描述 投票:5回答:2

它是有效的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 ...”错误消息)

c++ language-lawyer alias
2个回答
2
投票

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个成员


1
投票

[我认为目前标准无法回答谁是正确的,P1787R4: Declarations and where to find them似乎偏爱GCC和MSVC行为:

[basic.lookup]

附加段落:

在某些情况下,仅包括某些种类的声明。在进行任何此类限制之后,如果找到任何其他声明,则将丢弃任何类或枚举的声明。 [注意:因此,类型(但不是typedef名称或模板)在其范围内被任何其他实体隐藏。 — —尾注]但是,如果查找是仅类型的,则仅考虑类型和类型专门针对类型的模板的声明; 此外,如果找到typedef声明符及其引用类型的声明,则将typedef声明符代替类型声明而丢弃

© www.soinside.com 2019 - 2024. All rights reserved.