SFINEE是否在概念参数内起作用? (也许这里不叫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 /格式不正确,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-
答案 0 :(得分:1)
SFINAE仍然可以在约束条件下工作。
替换失败会导致原子约束(例如(!std::same_as<std::invoke_result_t<F, int>, void>)
)被视为不满足
[temp.constr.atomic]
3要确定是否满足原子约束, 参数映射和模板参数首先被替换为 它的表达。如果替换导致无效的类型或 表达式,不满足约束条件。否则, 如有必要,执行左值到右值转换,并且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
—结束示例]
在模板自变量推导过程中,未满足的约束导致推导过程不成功
[扣除温度]
5 ...如果功能模板具有关联的约束 ([temp.constr.decl]),检查这些约束是否满足要求 ([temp.constr.constr])。如果不满足约束条件,请键入 推论失败。
古老的SFINAE规范在重载解析期间仍然适用,因此当替换失败时,将不考虑重载。
[温度超过]
1 ...如果对于给定的函数模板,参数推导失败 否则综合功能模板的专业化将是 格式不正确,则不会将此功能添加到候选集 该模板的功能...
总而言之,GCC的行为符合人们的预期。