[Accepted as a DR at the November, 2024 meeting.]
Consider:
template<bool B> struct X { void f(short) requires B; void f(long); template<typename> void g(short) requires B; template<typename> void g(long); }; void test(X<true> x) { x.f(0); // #1, ambiguous x.g<int>(0); // #2, ambiguous &X<true>::f; // #3, OK! &X<true>::g<int>; // #4, ambiguous }
For the function call cases, 12.2.4.1 [over.match.best.general] bullet 2.6 and 13.7.7.3 [temp.func.order] paragraph 6 specify that constraints are only considered if the competing overloads are otherwise basically the same. There is no corresponding restriction when taking the address of a function.
For a second issue, the treatment of placeholder type deduction is unclear:
template<bool B> struct X { void f(short) requires B; void f(short); template<typename> void g(short) requires B; template<typename> void g(short); }; void test(X<true> x) { auto r = &X<true>::f; // #5 auto s = &X<true>::g<int>; // #6 }
When the address of the overload set is resolved, there is a target, but the target type is auto, which is not properly handled.
See also issue 2572.