在下面的程序模板函数
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
程序中是否有任何未定义的行为,如果没有,哪个编译器是正确的?
我不会假装我知道细节,但
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
的参数必须依赖于模板参数。
p
模板的声明是 IFNDR(格式错误,无需诊断),按照 https://eel.is/c++draft/temp#over.link-7.sentence-2:
这两个声明具有对应的签名(不考虑尾随的 require 子句),但它们并不对应,因为这确实需要等效的尾随的 require 子句。然而,如果它们确实对应,那么声明将(重新)声明相同的函数模板。
此外,两个函数模板接受并满足相同的模板参数列表。
requires true
不以任何形式约束模板。