Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why nested bind can defer evaluation of the expression

Tags:

c++

c++11

Item 34 in [Effective modern C++] gives an example that nested bind can defer evaluation of steady_clock::now() until setAlarm is invoked. std::chrono::steady_clock::now is actually a static member function. My understanding is that whenever it is passed as function argument, it will be evaluated.

Can anyone help to elaborate on why it can be deferred?

auto setSoundB =
    std::bind(setAlarm,
        std::bind(std::plus<>(), steady_clock::now(), 1h),
        _1,
        30s);
like image 729
SSY Avatar asked Feb 13 '17 15:02

SSY


1 Answers

In your example that call to steady_clock::now() is not deferred.

To prevent steady_clock::now() from evaluating now, wrap that in another bind call:

std::bind(&steady_clock::now)

E.g.:

auto mynow() {
    std::cout << "mynow\n";
    return std::chrono::steady_clock::now();
}

int main(int ac, char**) {
    std::cout << "creating a bind object\n";
    auto f = std::bind(std::plus<>(), mynow(), 1h);
    std::cout << "invoking bind object\n";
    f();


    std::cout << "\ncreating a bind object\n";
    auto g = std::bind(std::plus<>(), std::bind(&mynow), 1h);
    std::cout << "invoking bind object\n";
    g();
}

Outputs:

creating a bind object
mynow
invoking bind object

creating a bind object
invoking bind object
mynow

See std::bind for details:

Member function operator()

If the stored argument arg is of type T for which std::is_bind_expression<T>::value == true (for example, another bind expression was passed directly into the initial call to bind), then bind performs function composition: instead of passing the function object that the bind subexpression would return, the subexpression is invoked eagerly, and its return value is passed to the outer invokable object...

like image 154
Maxim Egorushkin Avatar answered Nov 14 '22 21:11

Maxim Egorushkin