c++ - 使用声明可以在 gcc 和 msvc 中编译,但在 clang 中被拒绝

标签 c++ language-lawyer c++20

我编写了以下程序来澄清我的使用声明概念。但令人惊讶的是,该代码使用 gcc 和 msvc 编译,但被 clang 拒绝。

namespace X 
{ 
    struct type {}; 
}
namespace Y 
{ 
    using type = int; 
}
using X::type;
using Y::type;
int main()
{
    auto i = sizeof(type); //gcc and msvc accepts this but clang rejects this
}

Check Demo

正如你所看到的,上面的程序是用 gcc 和 msvc 编译的,但是 clang 说:

<source>:13:21: error: reference to 'type' is ambiguous
    auto i = sizeof(type); 
                    ^
<source>:10:10: note: candidate found by name lookup is 'type'
using Y::type;
         ^
<source>:9:10: note: candidate found by name lookup is 'type'
using X::type;
         ^
<source>:13:21: error: reference to 'type' is ambiguous
    auto i = sizeof(type); 
                    ^
<source>:10:10: note: candidate found by name lookup is 'type'
using Y::type;
         ^
<source>:9:10: note: candidate found by name lookup is 'type'
using X::type;
         ^

我的问题是根据标准什么是正确的行为。这是正确的编译器。

最佳答案

C++23 之前版本

该程序格式错误(请参阅 gcc bug ),因为 using-declaration 是一个声明,因此它必须遵循声明规则。特别是,给定的两个 using-declaration 声明了一个名为 type 的类型(在全局命名空间),指两种不同的类型 X::typeY::type=int

接下来,不能有多个具有相同名称的类型声明(在同一范围内)引用两种不同类型。下面使用 C++ 标准更详细地解释了这一点:

同样来自using declaration's documentation :

Since a using-declaration is a declaration, the restrictions on declarations of the same name in the same declarative region also apply to using-declarations.

(强调我的)

下一步,basic.scope.declarative防止引用两种不同类型的同名声明(您的示例就是这种情况):

Given a set of declarations in a single declarative region, each of which specifies the same unqualified name,

  • they shall all refer to the same entity, or all refer to functions and function templates; or
  • exactly one declaration shall declare a class name or enumeration name that is not a typedef name and the other declarations shall all refer to the same variable, non-static data member, or enumerator, or all refer to functions and function templates; in this case the class name or enumeration name is hidden ([basic.scope.hiding]).

(强调我的)

由于 type 引用了 2 个不同的实体,因此该程序格式错误


检验上述结论

另请注意,除了上面引用的引用资料之外,您还可以通过在命名空间 中将 using type = int; 替换为 struct type{}; 来测试上述结论Y,您会注意到我们收到了预期的错误。 demo :

namespace X 
{ 
     struct type{};
}
namespace Y 
{ 
    struct type{};  
}
using X::type;
using Y::type;      //NOT ALLOWED since same name "type" refers to different structs

此外,如果您将上述程序更改为将 type 定义为与 int 相同的类型,那么程序将正常工作,因为这次名称引用相同的类型 intdemo

namespace X 
{ 
     using type= int ; 
}
namespace Y 
{ 
    using type= int;  
}
using X::type;
using Y::type;       //ALLOWED since "type" refer to same type int 

这是 gcc 错误:

GCC accepts invalid program with multiple using declarations


C++23

该程序在 C++23 中也是格式错误,但现在由于语句 auto i = sizeof(type); 而不是 使用 Y::类型;

来自 C++23 的[namespace.udecl]:

If a declaration named by a using-declaration that inhabits the target scope of another declaration potentially conflicts with it (6.4.1), and either is reachable from the other, the program is ill-formed. If two declarations named by using-declarations that inhabit the same scope potentially conflict, either is reachable from the other, and they do not both declare functions or function templates, the program is ill-formed.

[Note 4 : Overload resolution possibly cannot distinguish between conflicting function declarations. — end note]

(强调我的)

关于c++ - 使用声明可以在 gcc 和 msvc 中编译,但在 clang 中被拒绝,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76099741/

相关文章:

c++ - x64 free 性能低下

c++ - JPEG of Death 漏洞如何运作?

c++ - C++ 标准库中是否有保证不执行动态内存分配的函数或类?

c++ - 如何将 std::tuple 转换为 std::any?

c++ - 覆盖派生类中的模板基方法?

c++ - 使用 Boost::Spirit 解析具有未知键的 'key = value' 列表

C++17 标准 - 抛弃 const of static

c++ - 如何理解引用列表初始化中的纯右值

c++ - `std::tuple_size_v` 在不同编译器上的不同 SFINAE 行为

c++ - 什么是指定初始化器?