Search code examples
c++bindstdbind

execution order of functors in std::bind() parameter list (maybe not related to evaluation order of function parameter)


I was just wondering and write the following code: (I am not asking for work arounds, I just want to know whether bind() handles this perfectly or not). Besides, I think bind can handle this and define an order for it, but I am not sure or maybe it is just a parameter evaluation order issue.

#include <functional>
#include <utility>
#include <iostream>
using namespace std;
class increment{
public : 
    string operator()(int& x)
    {
        ++x;
        return string {"dumb_return_value"};
    }
};

class multiply{
public : 
    string operator()(int& x)
    {
        x = x * 2;
        return string {"dumb_return_value"};
    }
};

template <typename A, typename B>
class do_nothing{
public : 
    void operator()(A , B)
    {
        return;
    }
};


int main()
{
    int x = 0;
    increment increment_object;
    multiply multiply_object;
    do_nothing<string,string> do_nothing_object;

    bind(do_nothing_object,bind(increment_object,ref(x)),bind(multiply_object,ref(x)))();
    cout << x << endl;//output 2

    x = 0;
    bind(do_nothing_object,bind(multiply_object,ref(x)),bind(increment_object,ref(x)))();
    cout << x << endl;//output 1
}

compilation option : std=c++1z So, I use the reference semantics to amplify the difference here. What is the execution order of these sub-functions increment and multiply? Does bind handle this providently and define an order, or it is dependent on function parameter evaluation sequence, which is compiler-specific? If std::bind() handles this providently, please cite it, thanks!

PS: one reason why I ask this question is here: c++ equivalent of java's andThen function to composite new function?


Solution

  • Using this draft as reference.

    func.bind.bind [20.10.9.1.3] doesn't specify when the bind sub-expressions are evaluated or their order.

    It simply states that if one of the arguments to bind is a bind-expression result, the return value of the outer bind expression uses the result of calling the inner bind-expression with the arguments passed to the outer bind expression. It gives no sequencing information for when those values are evaluated; one may presume that it "must" happen after the outer bind expression is passed arguments, but that (as far as I can tell) only something I can conclude with common sense, not from the standard text itself.