简体   繁体   English

为什么bind1st和bind2nd需要常量函数对象?

[英]Why do bind1st and bind2nd require constant function objects?

So, I was writing a C++ program which would allow me to take control of the entire world. 因此,我正在编写一个C ++程序,它将使我能够控制整个世界。 I was all done writing the final translation unit, but I got an error: 我完成了最终翻译单元的编写,但出现错误:

error C3848: expression having type 'const `anonymous-namespace'::ElementAccumulator<T,BinaryFunction>' would lose some const-volatile qualifiers in order to call 'void `anonymous-namespace'::ElementAccumulator<T,BinaryFunction>::operator ()(const point::Point &,const int &)'
        with
        [
            T=SideCounter,
            BinaryFunction=std::plus<int>
        ]
        c:\program files (x86)\microsoft visual studio 9.0\vc\include\functional(324) : while compiling class template member function 'void std::binder2nd<_Fn2>::operator ()(point::Point &) const'
        with
        [
            _Fn2=`anonymous-namespace'::ElementAccumulator<SideCounter,std::plus<int>>
        ]
        c:\users\****\documents\visual studio 2008\projects\TAKE_OVER_THE_WORLD\grid_divider.cpp(361) : see reference to class template instantiation 'std::binder2nd<_Fn2>' being compiled
        with
        [
            _Fn2=`anonymous-namespace'::ElementAccumulator<SideCounter,std::plus<int>>
        ]

I looked in the specifications of binder2nd and there it was: it took a const AdaptibleBinaryFunction. 我查看了binder2nd的规范, binder2nd就是:它使用了const AdaptibleBinaryFunction。

So, not a big deal, I thought. 所以,我认为这没什么大不了的。 I just used boost::bind instead, right? 我只是使用boost::bind ,对吧?

Wrong! 错误! Now my take-over-the-world program takes too long to compile ( bind is used inside a template which is instantiated quite a lot)! 现在,我的“接管世界”程序花费了太长时间来编译( bind在模板中使用,实例化了很多)! At this rate, my nemesis is going to take over the world first! 以这种速度,我的克星将首先占领世界! I can't let that happen -- he uses Java! 我不能让这种事情发生-他使用Java!

So can someone tell me why this design decision was made? 那么有人可以告诉我为什么要做出这个设计决定吗? It seems like an odd decision. 这似乎是一个奇怪的决定。 I guess I'll have to make some of the elements of my class mutable for now... 我想我现在必须使班上的某些元素变得mutable ...

EDIT: The offending code: 编辑:令人反感的代码:

template <typename T, typename BinaryFunction>
class ElementAccumulator 
    : public binary_function<typename T::key_type, typename T::mapped_type, void>
{
public:
    typedef T MapType;
    typedef typename T::key_type KeyType;
    typedef typename T::mapped_type MappedType;
    typedef BinaryFunction Func;

    ElementAccumulator(MapType& Map, Func f) : map_(Map), f_(f) {}

    void operator()(const KeyType& k, const MappedType& v)
    {
        MappedType& val = map_[k];
        val = f_(val, v);
    }
private:
    MapType& map_;
    Func f_;
};

void myFunc(int n)
{
    typedef boost::unordered_map<Point, int, Point::PointHash> Counter;
    Counter side_count;
    ElementAccumulator<SideCounter, plus<int> > acc(side_count, plus<int>());

        vector<Point> pts = getPts();
    for_each(pts.begin(), pts.end(), bind2nd(acc, n));
}

binder2nd ctor takes a constant reference to an AdaptableBinaryFunction -- not a const AdaptableBinaryFunction per se. binder2nd构造函数需要一个恒定的参考AdaptableBinaryFunction - 不是一个const AdaptableBinaryFunction本身。 How's your instantiating-code? 您的实例化代码如何? One normally doesn't explicitly mention binder2nd but rather work through convenience function bind2nd (which simply works on the second argument x with a typename Operation::second_argument_type(x) or the like). 通常,通常不会显式地提到binder2nd ,而是通过便捷函数bind2nd (它简单地用于第二个参数x ,类型名称为typename Operation::second_argument_type(x)等)。

Well, attempting some deduction: 好吧,尝试一些推论:

The reason anything takes a const anything, is to permit someone to pass a const anything into it. 什么都需要const什么的原因是允许某人将const任何东西传递给它。

The most obvious const something that you want to pass into "functional" functions is a reference to a temporary. 您想要传递给“函数”函数的最明显的const就是对临时变量的引用。

In particular, if bind1st and other stuff in <functional> took a non-const reference parameter, then you couldn't chain them together to program in a functional style. 特别是,如果bind1st<functional>其他内容采用了非const引用参数,则无法将它们链接在一起以功能形式进行编程。 A functional style abhors the idea of capturing a temporary in a variable in one statement, and then "later" modifying that variable in "the next" statement. 一种功能风格令人讨厌在一个语句中捕获一个临时变量,然后在“下一个”语句中“稍后”修改该变量的想法。 All very imperative and side-effecty. 都非常必要和副作用。

Unfortunately, this means that as <functional> is defined, operator() of functors needs to be const in this case and presumably a bunch of other cases. 不幸的是,这意味着当定义了<functional> ,函子的operator()在这种情况下可能是常量,而在其他情况下则必须是常量。 Yours isn't. 你不是。

Does boost::bind allow either const or not as part of the template type where relevant? boost :: bind在相关时是否允许const作为模板类型的一部分? If so then maybe <functional> doesn't do this simply because boost::bind was designed once people had more idea how to get the best out of templates. 如果是这样的话,那么<functional>可能不会仅仅因为boost :: bind是在人们有了更多的想法如何从模板中获得最大的收益时才设计的。 Or maybe bind1st was designed with a purer functional mindset, hence no side-effects, hence why shouldn't everything be const? 或者也许bind1st设计采用了更纯净的功能思维方式,因此没有副作用,因此为什么不应该将所有内容都设为const? I may have missed part of the point of the question - I see from your code example why you want to use parameter binding, but I don't think it's obvious that a header called <functional> is the right place to look for anything involving accumulators ;-) 我可能已经错过了问题的一部分-我从您的代码示例中看到了为什么要使用参数绑定,但是我认为,显然不是标题为<functional>的标题是查找涉及以下内容的正确地方累加器;-)

bind (and the old, deprecated bind1st and bind2nd ) are value-semantic. bind (以及已弃用的旧bind1stbind2nd )是值语义的。 The return object is self-contained and it doesn't reference the parameters, const or not. 返回对象是自包含的,它不引用参数,无论是否为const

To get reference semantics instead, pass std::ref to bind . 要获取引用语义, std::ref传递给bind

auto defer_by_value = std::bind( fun, foo, bar ); // Copy fun, foo, and bar.

auto defer_by_ref = std::bind( std::ref( fun ), std::ref( foo ), std::ref( bar ) );
                                                  // Observe fun, foo, and bar.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM