use*_*522 18 c++ language-lawyer c++-concepts c++23
最新的标准草案N4910在 [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
};
Run Code Online (Sandbox Code Playgroud)
我的理解是,这没问题,因为C<42>
和true
是未评估的操作数。因此,根据[temp.over.link]/5,在考虑约束是否在功能上等价时,不是表达式的结果,而是对哪个实体执行什么操作以及以什么顺序执行,才是决定约束功能等价的。
但是,如果约束在功能上等效,那么由于它们不等效,根据[temp.over.link]/7,程序将格式错误,无需诊断,因为两次声明同一成员将使程序格式错误。
另一方面
template<typename>
requires C<42>
void g() {};
template<typename>
requires true
void g() {};
Run Code Online (Sandbox Code Playgroud)
似乎格式不正确,不需要诊断,因为[temp.over.link]/6表示如果模板头接受并满足相同的模板参数,则它们在功能上是等效的。
我是否误解了示例并引用了标准措辞,或者真的有这样的差异吗?如果是这样,为什么?
这是为了避免将约束修改为函数符号(请参阅:为什么返回类型中的 decltype 表达式必须在符号名称中修改?)。
考虑两个函数模板位于不同 TU 中的情况,x.cpp
并且y.cpp
:
// x.cpp
template<int> concept C = true;
template<typename> requires C<42> int g() { return 1; }
int x() {
volatile auto p = g<int>;
return p();
}
// y.cpp
template<typename> requires true int g() { return 2; };
int y() {
volatile auto p = g<int>;
return p();
}
Run Code Online (Sandbox Code Playgroud)
如果这是有效的,我们需要将约束修改为函数模板实例化符号,但我们真的(真的)不想这样做,因为这对于 ABI 兼容性来说是一个巨大的痛苦(我们永远不会能够收紧、放松甚至重构约束)以及实现者的轻微头痛。但它不可能是 ODR 格式错误的 NDR,因为要使其违反 ODR,我们必须确定这两个函数模板在功能上是等效的,这是不可判定的(Church)。因此,我们制作了等效但功能不等效的自己的 IFNDR。
然而,对于类模板成员函数则不会出现这个问题;类不能重新声明成员函数,并且必须在 TU 内完成,并且跨 TU 的类定义必须是标记级等效的。因此,允许两个不同的成员函数声明是没有问题的,因为无论如何都不能引用它们。嗯... - https://github.com/cplusplus/CWG/issues/256
归档时间: |
|
查看次数: |
500 次 |
最近记录: |