SFINAE 内部概念模板参数

SFINAE inside concept template argument

SFINAE 在概念论证中起作用吗? (也许这里不叫SFINAE)。示例:

template <class F>
    requires
        std::invocable<F, int> && // <-- is this needed?
        (!std::same_as<std::invoke_result_t<F, int>, void>)
auto foo(F f, int a) -> int

是否需要以上std::invocable<F, int>

如果我们这样省略它:

template <class F>
    requires (!std::same_as<std::invoke_result_t<F, int>, void>)
auto foo(F f, int a) -> int

即使 std::invoke_result_t<F, int> 不是(即,如果它不可调用)这个版本是否格式正确,还是 UB/ill 格式正确,ndr?

foo(11, 24);
// std::invoke_result_t<int, int> does not exist,
// is the second variant the one without `std::invocable<F, int>` ok in this case?

gcc 似乎没有它的表现:https://godbolt.org/z/SEH94-

SFINAE 仍然有限制。

替换失败导致原子约束(例如(!std::same_as<std::invoke_result_t<F, int>, void>))被视为不满足

[temp.constr.atomic]

3 To determine if an atomic constraint is satisfied, the parameter mapping and template arguments are first substituted into its expression. If substitution results in an invalid type or expression, the constraint is not satisfied. Otherwise, the lvalue-to-rvalue conversion is performed if necessary, and E shall be a constant expression of type bool. The constraint is satisfied if and only if evaluation of E results in true. If, at different points in the program, the satisfaction result is different for identical atomic constraints and template arguments, the program is ill-formed, no diagnostic required. [ Example:

template<typename T> concept C =
  sizeof(T) == 4 && !true;      // requires atomic constraints sizeof(T) == 4 and !true

template<typename T> struct S {
  constexpr operator bool() const { return true; }
};

template<typename T> requires (S<T>{})
void f(T);                      // #1
void f(int);                    // #2

void g() {
  f(0);                         // error: expression S<int>{} does not have type bool
}                               // while checking satisfaction of deduced arguments of #1;
                                // call is ill-formed even though #2 is a better match

— end example ]

在模板参数推导过程中,不满足的约束导致推导过程不成功

[temp.deduct]

5 ... If the function template has associated constraints ([temp.constr.decl]), those constraints are checked for satisfaction ([temp.constr.constr]). If the constraints are not satisfied, type deduction fails.

旧的 SFINAE 规范在重载决策期间仍然适用,因此当替换失败时,不考虑重载。

[temp.over]

1 ... If, for a given function template, argument deduction fails or the synthesized function template specialization would be ill-formed, no such function is added to the set of candidate functions for that template ...

所以总而言之,GCC 的行为是正确的,正如人们所期望的那样。