不同C++文件中未命名命名空间中的名称是否可以引用相同的命名事物?

3

在这个问题上,Clang和GCC存在不同的看法:

使用g ++时,将打印“result2”,但是使用clang ++时将打印“result1”。

我知道g ++认为由g()抛出的A与main.cpp中的A不同。
但是,clang++是否有任何问题?

版本信息:
g ++:7.4.0
clang:10.0.0

main.cpp:

#include <iostream>

namespace {
  struct A {};
}

extern void g();

int main()
{
  try {
    try {
      g();
    } catch (A) {std::cout << "result1\n";}
  } catch (...) {std::cout << "result2\n";}
}

other.cpp:

namespace {
  struct A {};
}

void g() { throw A(); }

3
也许你应该修改你的问题为“根据C++ 2017标准哪个是正确的?”,以使其更具普遍性。 - kabanus
它应该始终是 result2,因为未命名的命名空间使类型局部于翻译单元。 - Maciej Załucki
1个回答

6
这里的A名称具有内部链接(internal linkage),在不同的翻译单元中它们不可能指向相同的事物。在这种情况下,GCC是正确的;一些实现使用名称来实现RTTI,这可能是问题的原因。

它们在不同的翻译单位中不可能指代相同的东西。嗯。https://timsong-cpp.github.io/cppwp/n4659/basic.link#9说:“如果两个名称相同且在不同作用域声明,那么它们应该表示同一个变量、函数、类型、模板或命名空间**如果**……”,但在“**如果**”之后没有“**当且仅当**”。 - Language Lawyer
@LanguageLawyer:请参阅(不幸的是含糊不清的)basic.link/3CWG1884:这段话不应被理解为指定两个声明声明相同实体的时间。 - Davis Herring
@LanguageLawyer 我注意到,如果我们编写相同的代码但使用命名空间,clang和g++都会打印 result1。这完全合乎逻辑吗?我认为至少应该得到一个重新定义。 - Afshin
@DavisHerring 啊,我想我误读了[basic.link]/9。它说:“两个相同且已声明的名称”。我忽略了这个“已声明”(或者更确切地说是将其读成了“使用/提到”之类的),并认为这段适用于throw A();catch(A)中的A - Language Lawyer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接