SFINAE内概念模板参数

问题描述 投票:3回答:1

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-

c++ sfinae c++20 c++-concepts
1个回答
1
投票

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的表现是正确的,正如人们所期望的那样。

© www.soinside.com 2019 - 2024. All rights reserved.