传递受概念约束的函数重载

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 案例和不受约束的案例一样相关。