【问题标题】:What is the effect of the pipe operator in c++ boost::adaptors::filtered?c++ boost::adaptors::filtered中管道运算符的作用是什么?
【发布时间】:2018-09-14 11:01:46
【问题描述】:

在boost::adaptors::filtered 中,过滤函数的使用方式如下:

std::vector<int> input;
input += 1,2,3,4,5,6,7,8,9;

boost::copy(
        input | filtered(is_even()),
        std::ostream_iterator<int>(std::cout, ","));

在这种情况下管道运算符的作用是什么?不是为std::vector 定义的,是不是超载了?如果是这样,如何在 boost 等库中有效地搜索此类运算符?

【问题讨论】:

  • 我已经迷失在input += 1,2,...。
  • @user463035818 感谢大家的支持,通常人们不得不害怕承认这样的事情。
  • 有效搜索:IDE 救援,使用 C/C++ (ms-vscode.cpptools) 的 Visual Studio Code 在悬停时提供以下工具提示:boost::range_detail::filtered_range&lt;...&gt; boost::range_detail::operator|&lt;std::__1::vector&lt;int, std::__1::allocator&lt;int&gt;&gt;, is_even&gt;(std::__1::vector&lt;...&gt; &amp;r, const boost::range_detail::filter_holder&lt;...&gt; &amp;f) +2 overloads

标签: c++ boost


【解决方案1】:

这是Boost Range Adaptor。在online book "The Boost C++ Libraries" 中编写了更多文档。

这样的范围有很多,可以组合写出高级函数效果。示例如下:

filtered 适配器

input | filtered(is_even()) 创建适配器类型的临时实例:

boost::range_detail::filtered_range<is_even, std::vector<int> >

这是一种模拟范围概念的类型,并持有对源范围 (input) 的引用以及过滤谓词 (is_even()) 的副本。

然后实现范围概念,使得范围的迭代产生一个双向范围,就好像它只有源范围中满足过滤谓词的元素一样。你也可以这样写:

is_even predicate;
for (auto const& i : input)
    if (predicate(i))
        std::cout << i << ",";

range | adaptor 是一个表达式模板,可以生成一个新的自适应 范围。

它如何/为什么与 | 一起使用?

真正的答案是“因为它是这样设计和记录的”。更技术性的解释是因为filtered(is_even()) 是boost::range_detail::filter_holder&lt;is_even&gt; 类型,它有一个重载的operator |:

template< class SinglePassRange, class Predicate >
inline filtered_range<Predicate, SinglePassRange>
operator|(SinglePassRange& r,
          const filter_holder<Predicate>& f)
{
    BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept<SinglePassRange>));
    return filtered_range<Predicate, SinglePassRange>( f.val, r );
}

注意:断言仅验证最低所需的遍历类别。如文档所述,您将获得"The minimum of the range category of rng and Bidirectional Range",在这种情况下它是一个双向范围(因为向量具有随机遍历)。

另一件事

我已经迷失在输入 += 1,2,.... – user463035818 56 分钟前

那是 Boost Assign,与范围适配器无关,我敢说 C++11 让它在很大程度上已经过时了,因为你可以很容易地说

std::vector<int> input { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

确实

std::vector<int> input;
input.insert(input.end(), { 1, 2, 3, 4, 5, 6, 7, 8, 9 });

【讨论】:

  • +1 引用了我的高质量声明:P。老实说,我几乎可以肯定这段代码一定是愚人节的玩笑。出于好奇,我尝试实现这个+= 1,2,3 的东西,它非常简单,但我同意它已经过时,我什至会说它不是一个很好的运算符重载用法。
  • 顺便说一句,至少我最感兴趣的是“如果是这样,如何在像 boost 这样的库中有效地搜索这样的运算符?”问题的一部分,您在回答中并未真正解决
  • @user463035818 你没有。您只需查看代码,查看using namespace boost::assign 并从那里开始。这是有问题的库设计,尽管我知道人们在 c++11 之前迫切需要简洁的容器初始化程序。 (而且,当然我没有在我的回答中提到那部分,因为它从来都不是问题的一部分,它是由其他人发布的,甚至:))
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-23
  • 1970-01-01
  • 1970-01-01
  • 2012-12-27
  • 1970-01-01
  • 1970-01-01
  • 2011-06-11
相关资源
最近更新 更多