c++ - 为什么使用整数类型约束 auto 使其不可用于 views::filter?

标签 c++ c++20 c++-concepts

我写了一个简单的谓词,我想把它传递给 std::ranges::views::filter :

struct even_fn {
    constexpr
    bool operator()(std::integral auto&& e) const noexcept {
        return e % 2 == 0;
    }
};

inline constexpr even_fn even;
示例用法:
using namespace std::ranges;
views::iota(1, 10) | views::filter(even);
这失败了一大堆错误,我认为最有意义的是:
note: the expression 'is_invocable_v<_Fn, _Args ...> [with _Fn = even_fn&; _Args = {std::__detail::__cond_value_type<int>::value_type&}]' evaluated to 'false'

但是,如果我删除 std::integral部分来自我的运算符(operator)(只留下 auto&& ),代码编译成功。这是为什么?这有什么特别之处__cond_value_type当我们有约束仿函数时会中断吗?

最佳答案

这是因为 std::integral不允许推断引用类型。
实际上,过滤器 View 将使用以下内容进行过滤:

filter_function(*it);
这对于大多数范围类型将返回对元素的左值引用。
因为它发送一个左值引用,所以调用你的函数的唯一方法是推导出 int& ,所以引用折叠工作是这样的:int& && --> int& .没有那个用左值调用你的函数是不可能的。
但是int&不是整数类型,因此您的错误!
那你怎么能让你的过滤器工作呢?
只需删除转发引用并使用 const 左值引用:
struct even_fn {
    constexpr
    bool operator()(std::integral auto const& e) const noexcept {
        return e % 2 == 0;
    }
};
这样,当从 int 左值推导出来时,只需 int将被推断使调用工作。

使用概念模板参数,可以使用更高阶的概念来使这种情况起作用:
template<typename T, concept C>
concept forwarded = C<std::remove_cvref_t<T>>;
并像这样使用它:
struct even_fn {
    constexpr
    bool operator()(forwarded<std::integral> auto&& e) const noexcept {
        return e % 2 == 0;
    }
};

关于c++ - 为什么使用整数类型约束 auto 使其不可用于 views::filter?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63922144/

相关文章:

c++ - 在什么意义上 weak_ptr 'own' 是 shared_ptr?

c++ - 约束包含仅适用于概念吗?

C++ 概念 Same 和 Assignable

c++ - 用什么来替代 C++ 中的概念(即将推出的功能)?

c++ - 是否可以定义一个包含函数和 lambda 的可调用概念?

c++ - pthread_create 将动态 vector 数组传入参数

c++ - C++ 中奇怪的编码错误

c++ - 在整数数组上使用 stoul 时 std::string 的输出错误

c++ - 用概念检查属性的类型

c++ - P1236R1 : Why is the c++ standard trying to move away from the word "bit" when defining integers?