14

I'm having a look at the Boost libraries that were included in C++'s Technical Report 1 and trying to understand what each does.

I've just finished running an example for boost::mem_fn and now I'm wondering what's the point of using it instead of the better boost::bind. As far as I understand, both of them return a function object pointing to a member function. I find mem_fn so limited that I can't find a scenario where using it would be better than bind.

Am I missing something? Is there any case in which bind cannot replace mem_fn?

José Tomás Tocino
  • 9,873
  • 5
  • 44
  • 78

4 Answers4

7

mem_fn is much smaller than bind, so if you only need the functionality of mem_fn it's a lot less code to pull in.

Jeff Hardy
  • 7,632
  • 24
  • 24
6

mem_fn is smaller and faster than bind. Try the following program with your favorite compiler and compare:

  1. The size of the resulting executable and
  2. The number of seconds reported as being spent.

You can compare the performance of bind versus mem_fn by changing the 1 to a 0 in the #if line.

#include <iostream>
#include <functional>
#include <chrono>

struct Foo
{
    void bar() {}
};

int main(int argc, const char * argv[])
{   
#if 1
    auto bound = std::bind( &Foo::bar, std::placeholders::_1 );
#else
    auto bound = std::mem_fn( &Foo::bar );
#endif
    Foo foo;
    auto start = std::chrono::high_resolution_clock::now();
    for( size_t i = 0; i < 100000000; ++i )
    {
        bound( foo );
    }
    auto end = std::chrono::high_resolution_clock::now();
    auto delta = std::chrono::duration_cast< std::chrono::duration< double >>( end - start );
    std::cout << "seconds = " << delta.count() << std::endl;
    return 0;
}

Results will vary, but on my current system the mem_fn version of the executable is 220 bytes smaller and runs about twice as fast as the bind version.

And as a bonus feature, mem_fn doesn't require you to remember to add std::placeholders::_1 like bind does (on pain of an obscure templated compiler error).

So, prefer mem_fn when you can.

OldPeculier
  • 11,049
  • 13
  • 50
  • 76
  • I think GCC optimizations will make the speed efficiency about the same for both. I just tested using "-O2" with your code (and printing something in the "bar" function, else the optimizer will see it is doing nothing). Sometimes the "bind" version is even faster. – felipou Apr 17 '14 at 10:07
  • You should add something like `static volatile int i; i;` into the `bar` body, otherwise compiler may optimize empty function call (what really happens in my case with both `bind` and `mem_fn`). The benchmark results for `bind` and `mem_fn` is equal on my PC (*gcc 4.9*, `-O3`), `mem_fn` is not faster than `bind`. – anton_rh Apr 10 '16 at 14:01
2

Well, bind depends on mem_fun so there you go. How and why I'll leave for you to discover since although interesting, I haven't got the time to investigate right now (bind is complicated).

Edward Strange
  • 40,307
  • 7
  • 73
  • 125
1

boost::lambda has a similar overlap of functionality with the two you mentioned. I think they all sort of evolved with similar intent, about the same time, with different approaches, resulting in confusion and incompatibility issues. It'd be nice if they all merged under one lambda umbrella.

So, no, there is no overarching design that calls for both libraries to co-exist.

John
  • 59
  • 1
  • 3
    The curious thing is that both `bind` and `mem_fn` have made it to the C++ Technical Report 1, and the C++ comittee is supposed to be quite strict. Didn't they realize they we're duplicating functionalities? – José Tomás Tocino Jun 21 '10 at 20:48