c – 如何正确转发Invocable类型

我真的很喜欢使用 cmcstl2,Ranges TS的实现.我特别喜欢每个STL算法的可选投影.可调用类型转发(嗯……或不),如下所示:( min_element.hpp)
template <ForwardIterator I,Sentinel<I> S,class Comp = less<>,class Proj = identity>
requires
    IndirectStrictWeakOrder<
        Comp,projected<I,Proj>>()
I min_element(I first,S last,Comp comp = Comp{},Proj proj = Proj{});

template <ForwardRange Rng,projected<iterator_t<Rng>,Proj>>()
safe_iterator_t<Rng>
min_element(Rng&& rng,Proj proj = Proj{})
{
    return __stl2::min_element(__stl2::begin(rng),__stl2::end(rng),__stl2::ref(comp),__stl2::ref(proj));
}

作为参考:range-v3库实现如下:(min_element.hpp)

struct min_element_fn {
        template<typename I,typename S,typename C = ordered_less,typename P = ident,CONCEPT_REQUIRES_(ForwardIterator<I>() && Sentinel<S,I>() &&
                IndirectRelation<C,P>>())>
        I operator()(I begin,S end,C pred = C{},P proj = P{}) const;

        template<typename Rng,typename I = range_iterator_t<Rng>,CONCEPT_REQUIRES_(ForwardRange<Rng>() &&
                IndirectRelation<C,P>>())>
        range_safe_iterator_t<Rng> operator()(Rng &&rng,P proj = P{}) const
        {
            return (*this)(begin(rng),end(rng),std::move(pred),std::move(proj));
        }
};

现在我试着理解两种方法的区别和推理.
为什么我要按值使用Invocable类型呢?
为什么我不应该为这些类型使用完美转发?

我比第一种方法更了解第二种方法,因为我理解按值获取接收参数的方法.

解决方法

两个原因:

>我对标准库规范的阅读是算法可以根据需要多次复制用户函数对象,但是被指定在单个实例上执行所有调用.由于cmcstl2经常根据其他算法实现算法,因此满足该要求的最简单方法是通过reference_wrapper在内部传递函数对象.例如,binary_search调用lower_bound,然后确定由下限表示的元素是否完全匹配.它将reference_wrappers传递给compare_bound并将项目函数对象传递给lower_bound,以便稍后可以调用相同的实例.
>大型和/或可变功能对象可能很少见,但没有理由在标准库中必须支持它们.复制通常很便宜,并且移动几乎总是如此,但通过引用传递“从不”昂贵. cmcstl2最小化两个副本的用户功能对象的移动. (“never”上的空中引号表示,如果别名分析被函数对象引用混淆,那么通过引用传递会给优化器带来更大的负载,增加编译时间并可能在极端情况下生成较差的代码.)

这种推理有一些明显的漏洞.对我来说最重要的是“如果函数对象可能是有用的,那么算法不应该返回它们以保留该状态,std :: for_each也是如此?” cmcstl2的设计基本上违反了编程元素所谓的“有用回归定律”.我们是否应该使标准算法的签名复杂化以返回多达三个函数对象 – 比如比较器和两个投影 – 以容纳0.1%的用例?我认为这里显而易见的答案是“不”,特别是考虑到解决方法很简单:传递一个reference_wrapper.

那么,为什么cmcstl2一般 – 以及标准C的std :: for_each特别是 – 当解决方法类似于传递reference_wrapper时,它们会不会适应大型和/或可变函数对象?似乎cmcstl2的设计者在这里犯了同样的错误,就像LWG让std :: for_each返回它的函数对象一样.

相关文章

/** C+⬑ * 默认成员函数 原来C++类中,有6个默认成员函数: 构造函数 析构函数 拷贝...
#pragma once // 1. 设计一个不能被拷贝的类/* 解析:拷贝只会放生在两个场景中:拷贝构造函数以及赋值运...
C类型转换 C语言:显式和隐式类型转换 隐式类型转化:编译器在编译阶段自动进行,能转就转,不能转就编译...
//异常的概念/*抛出异常后必须要捕获,否则终止程序(到最外层后会交给main管理,main的行为就是终止) try...
#pragma once /*Smart pointer 智能指针;灵巧指针 智能指针三大件//1.RAII//2.像指针一样使用//3.拷贝问...
目录&lt;future&gt;future模板类成员函数:promise类promise的使用例程:packaged_task模板类例程...