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>
是没有(即如果它不可调用),还是它是UBill形成的,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.orgzSEH94-
SFINAE仍然与约束一起工作。
替换失败会导致一个原子约束(如 (!std::same_as<std::invoke_result_t<F, int>, void>)
)视为不满足
[temp.constr.atomic]
3 为了确定一个原子约束是否满足,首先将参数映射和模板参数替换到它的表达式中。如果代入的结果是无效类型或表达式,则约束不满足。否则,必要时进行l值到r值的转换,E应为类型为bool的常量表达式。如果且仅当E的评价结果为真时,约束才会得到满足。如果在程序的不同点,对于相同的原子约束和模板参数,满足结果是不同的,则程序是不合格的,不需要诊断。[ 示例。
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 ... 如果函数模板有相关约束([temp.constr.decl]),则检查这些约束是否满足([temp.constr.constr])。如果约束条件不满足,类型演绎就会失败。
在过载解析过程中,古老的SFINAE规范仍然适用,所以当替换失败时,过载不被考虑。
[temp.over]
1 ... 如果对于一个给定的函数模板,参数推导失败或合成的函数模板特殊化将是不合格的,那么该模板的候选函数集合中就不会添加这样的函数......。
所以总的来说,GCC的表现是正确的,正如人们所期望的那样。