最新的标准草案N4910在[ www.example.com ]中有temp.over.link关于功能等同的示例:
template<int I> concept C = true;
template<typename T> struct A {
void f() requires C<42>; // #1
void f() requires true; // OK, different functions
};
我的理解是这是可以的,因为C<42>
和true
是未求值的操作数。因此,根据[temp.over.link]/5,当考虑约束是否在功能上等效时,不是表达式的结果,而是在哪个实体上执行什么操作以及以什么顺序执行时,决定约束的功能等效。
然而,如果约束在功能上是等效的,那么由于它们不等效,到[temp.over.link]/7,程序将是病态的,不需要诊断,因为声明相同成员两次将使程序病态。
另一方面
template<typename>
requires C<42>
void g() {};
template<typename>
requires true
void g() {};
似乎是格式错误的,不需要诊断,因为[temp.over.link]/6说,如果模板头接受并满足相同的模板参数,则它们在功能上是等效的。
我是否误解了示例和引用的标准措辞,或者是否真的存在这样的差异?如果是,为什么?
2条答案
按热度按时间r7xajy2e1#
这样做是为了避免将约束插入函数符号(参见:Why decltype expressions in return types have to be mangled in the symbol name?)。
考虑两个函数模板位于不同TU
x.cpp
和y.cpp
中的情况:如果这是有效的,我们需要将约束插入函数模板示例化符号中,但是我们真的(* 真的 *)不想这样做,因为这会给ABI兼容性带来巨大痛苦(我们将永远无法收紧、放松甚至重构约束),也是实现者的一个小麻烦。因为要使其成为ODR违规,我们必须确定两个函数模板在功能上是等效的,这是不可判定的(Church),所以我们使等效但功能不等效的模板成为其自己的IFNDR。
但是,对于类模板成员函数不会出现这个问题;类不能重新声明成员函数,必须在TU内完成,跨TU的类定义必须是令牌级等价的。因此,允许两个不同的成员函数声明是没有问题的,因为它们无论如何都不能被引用。Well...-https://github.com/cplusplus/CWG/issues/256
k10s72fa2#
不同之处可能是在
struct A
中有两组函数(“不同的函数”),因为:满足概念C<x>
!=满足true
。在
g
的函数声明中,您试图让两个函数具有相同的求值要求,因此会出现类似于两个相同签名的错误。