编译器在使用参数相关查找和约束表达式的重载解析上存在分歧

问题描述 投票:0回答:2

在下面的程序模板函数

f
调用重载模板函数
p
并且其中一个重载是在
f
之后声明的,但据我了解,必须使用依赖于参数的查找在实例化点找到它:

struct A{};

constexpr bool p(auto) { return false; }
constexpr bool f(auto v) { return p(v); }
constexpr bool g() { return f(A()); }
constexpr bool p(auto) requires true { return true; }

static_assert( f(A{}) );

static_assert
仅在使用
-O0
选项的情况下在MSVC和GCC中通过,而在使用
-O1
和更高优化选项的Clang和GCC中则失败。在线演示:https://godbolt.org/z/crvE5azWe

程序中是否有任何未定义的行为,如果没有,哪个编译器是正确的?

c++ language-lawyer c++20 c++-concepts overload-resolution
2个回答
0
投票

我不会假装我知道细节,但

requires true
可能是这里的问题。

通过此修改,跨编译器的行为是一致的(并且是负面的):

struct A{};

constexpr bool p(auto) { return false; }
constexpr bool f(auto v) { return p(v); }
constexpr bool g() { return f(A()); }
constexpr bool p(auto arg) requires sizeof(&arg) { return true; }

static_assert( f(A{}) );

int main() {}

如果您认为

requires
是一个荣耀的
std::enable_if
,我认为这是有道理的。
enable_if
的参数必须依赖于模板参数。


0
投票

p
模板的声明是 IFNDR(格式错误,无需诊断),按照 https://eel.is/c++draft/temp#over.link-7.sentence-2:

这两个声明具有对应的签名(不考虑尾随的 require 子句),但它们并不对应,因为这确实需要等效的尾随的 require 子句。然而,如果它们确实对应,那么声明将(重新)声明相同的函数模板。

此外,两个函数模板接受并满足相同的模板参数列表。

requires true
不以任何形式约束模板。

© www.soinside.com 2019 - 2024. All rights reserved.