Skip to content

Deprecated binders and adaptors

April 25, 2012

Along with variadic templates have come much more flexible function binders and adaptors; as a result, several existing binders and adaptors are now deprecated. You should no longer use the functions ptr_fun, mem_fun, bind1st and bind2nd. Their functionality has been completely subsumed by the class std::function and the functions bind and mem_fn. Note that the deprecated function is mem_fun, and the new function is mem_fn, the only difference being the letter u.

Member functions

The function mem_fn takes a pointer to a member function of any class, and returns a functor whose first argument is an object of the required class, and whose remaining arguments are the arguments that the function expects. When called it will call the member function with the given object and the given arguments.

For example, suppose that you have the class A:

class Person
{
  public:

  Person(const std::string& name)
  : m_name(name) {}
  
  void
  hello() const
  {
    std::cout << "hello " << m_name;
  }

  std::string m_name;
}

You could create two objects of type Person, and create the one member function object to the same function on both objects:

Person bob("Bob");
Person jim("Jim");
auto hello = std::mem_fn(&Person::hello);
hello(bob);
hello(jim);

These lines will print to standard output:

hello Bob
hello Jim

The functions bind1st and bind2nd have been deprecated by bind. Furthermore, bind makes use of placeholders _M, where M is an integer whose value is implementation defined. Using bind with placeholders allows any argument to be bound to any position, for example, the function swap_args defined below creates a function that calls the given function with its two arguments swapped.

namespace ph = std::placeholders;

template <typename F>
auto
swap_args(F&& f)
  -> decltype(std::bind(f, ph::_2, ph::_1))
{
  using namespace std::placeholders;
  return std::bind(f, _2, _1);
}

Then you could write:

int main()
{
  std::cout << swap_args(std::divides<double>())(4, 2) 
            << std::endl;

  return 0;
}

Note that the result is 0.5, which is 2 divided by 4, the result of calling std::divides with the arguments 4 and 2 swapped. Note also that with bind, you are free to bind whichever arguments you wish to a function, you can also bind constant values, for example, you could bind the value 2 to the first argument, and the 4th passed argument to the second argument in the called function, completely ignoring the 1st, 2nd and 3rd arguments:

auto bound = std::bind(f, 2, _4);

Finally, the class function allows you to create a functor from any type of callable object: a member function wrapper, a function created with bind, a plain function pointer, etc. For example, in the example given above, we could attach the result of swap_args to a function object like so:

std::function<double(double, double)> f = 
  swap_args(std::divides<double>());

The class function takes a function-type argument. The syntax is t(a, b, ...), where t is the return type, and the remaining letters are the types of the arguments.

Advertisements

From → Uncategorized

Leave a Comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: