SFINAE inside concept template argument

我的梦境 提交于 2021-01-27 06:29:08

问题


Does SFINAE work inside a concept argument? (maybe it's not called SFINAE here). Example:

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

Is the above std::invocable<F, int> required?

If we omit it like so:

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

Is this version well-formed even if std::invoke_result_t<F, int> is not (i.e. if it is not invocable) or is it UB/ill formed, 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 seems to behave without it: https://godbolt.org/z/SEH94-


回答1:


SFINAE still works with constraints.

A substitution failure results in an atomic constraint (such as (!std::same_as<std::invoke_result_t<F, int>, void>)) being deemed as not satisfied

[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 ]

During template argument deduction, an unsatisfied constraint causes the deduction process to be unsuccessful

[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.

The age old SFINAE specification still applies during overload resolution, so when substitution fails, the overload is not considered.

[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 ...

So all in all, GCC behaves correctly, as one should expect.



来源:https://stackoverflow.com/questions/61847693/sfinae-inside-concept-template-argument

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!