是否需要实施来诊断同一 TU 内同一显式专业化的重复定义的 ODR 违规?

Is an implementation required to diagnose ODR-violations of duplicated definitions of the same explicit specialization within the same TU?

考虑一个模板化实体,比如 (A) 函数模板,以及 (B) class 模板的成员枚举。

// (A)
template<auto>
int f();

// (B)
template <auto>
struct T { enum class E; };

由于对此类模板实体的相同显式专业化的重复定义,是否需要实施来诊断 ODR 违规?或者,换句话说,[basic.def.odr]/1 是否申请显式专业化?


例如,GCC 和 Clang 都将以下程序诊断为格式错误:

// Single translation unit;
// primary template of 'f' declared as in (A) above.
template<>
int f<0>() { return 0; }

template<>
int f<0>() { return 1; }  
  // GCC & Clang - error: redefinition of 'int f() [with auto <anonymous> = 0]'

而只有 Clang 将以下程序诊断为格式错误,而 GCC 接受它:

// Single translation unit;
// primary template of 'T' defined as in (B) above.
template<>
enum class T<0>::E { ex };

template<>
enum class T<0>::E { ey };
  // Clang only - error: redefinition of 'E'

NDR 格式错误,还是格式错误? (/两个编译器都正确,还是 GCC 错误?)


针对 -std=c++17-std=c++2a 在各种 GCC 和 Clang 版本上进行了测试,结果相同

Is an implementation required to diagnose ODR-violations due to duplicated definitions of the same explicit specialization of such a template entity?

是的。

虽然[temp.spec]/5.2 specifies that multiple definitions of an explicit specialization in a program is ill-formed (whilst referring to [basic.def.odr]) NDR (no diagnostic required), multiple definitions within a single TU falls under [basic.def.odr]/1,例如class 模板(对于某些设置模板参数)的显式特化是 class.

No translation unit shall contain more than one definition of any variable, function, class type, enumeration type, or template.

违反 [basic.def.odr]/1 不是 NDR,实现应诊断它,GCC 和 Clang 都这样做是为了违反 ODR 的显式特化(在同一 TU 内):

  • 函数模板,以及
  • class 个模板,并且
  • 可变模板,并且
  • class 个模板的成员函数,以及
  • class 个模板的静态数据成员,以及
  • class 个模板的 class 个成员。

但是,只有 Clang 诊断它是否存在 TU-local ODR-violations 以明确特化 class 模板的成员枚举,这正是问题中使用的示例。

因此,成员枚举的这个未诊断案例是一个 GCC 错误(作为此问题的一部分提交):