传递受概念约束的函数重载
Passing a concept-constrained function overload
以下代码编译失败(Godbolt link):
#include <concepts>
template <class Fn>
decltype(auto) g(Fn&& fn) { return fn(); }
template <typename T>
requires(std::integral<T>) int f() { return 0; }
template <typename T>
int f() { return 1; }
int main() {
f<int>();
f<void>();
g(f<int>); // error: invalid initialization of non-const reference of type 'int (&)()'
// from an rvalue of type '<unresolved overloaded function type>'
g(f<void>);
}
我似乎出乎意料的是,在调用 f<int>()
时重载解析成功(选择受约束版本作为比无约束版本更好的匹配)但在传递 f<int>
作为参数时失败。
请注意,将无约束版本更改为不相交约束确实可以编译 (Godbolt link):
#include <concepts>
template <class Fn>
decltype(auto) g(Fn&& fn) { return fn(); }
template <typename T>
requires(std::integral<T>) int f() { return 0; }
template <typename T>
requires(!std::integral<T>) int f() { return 1; }
int main() {
f<int>();
f<void>();
g(f<int>);
g(f<void>);
}
那么编译器的行为是否正确?如果是这样,这是标准中的不一致,还是它打算以这种方式工作?
似乎 GCC 和 Clang 都没有完全实现形成约束函数指针的规则:[over.over]/5 肯定 在选择一个超载。这些有一些 late changes,尽管它们与 disjoint-constraints 案例和不受约束的案例一样相关。
以下代码编译失败(Godbolt link):
#include <concepts>
template <class Fn>
decltype(auto) g(Fn&& fn) { return fn(); }
template <typename T>
requires(std::integral<T>) int f() { return 0; }
template <typename T>
int f() { return 1; }
int main() {
f<int>();
f<void>();
g(f<int>); // error: invalid initialization of non-const reference of type 'int (&)()'
// from an rvalue of type '<unresolved overloaded function type>'
g(f<void>);
}
我似乎出乎意料的是,在调用 f<int>()
时重载解析成功(选择受约束版本作为比无约束版本更好的匹配)但在传递 f<int>
作为参数时失败。
请注意,将无约束版本更改为不相交约束确实可以编译 (Godbolt link):
#include <concepts>
template <class Fn>
decltype(auto) g(Fn&& fn) { return fn(); }
template <typename T>
requires(std::integral<T>) int f() { return 0; }
template <typename T>
requires(!std::integral<T>) int f() { return 1; }
int main() {
f<int>();
f<void>();
g(f<int>);
g(f<void>);
}
那么编译器的行为是否正确?如果是这样,这是标准中的不一致,还是它打算以这种方式工作?
似乎 GCC 和 Clang 都没有完全实现形成约束函数指针的规则:[over.over]/5 肯定 在选择一个超载。这些有一些 late changes,尽管它们与 disjoint-constraints 案例和不受约束的案例一样相关。