Showing posts with label function object. Show all posts
Showing posts with label function object. Show all posts

Friday, October 6, 2017

It's magic! std::bind

'std::bind' is a powerful helper for working around 'std::function'.

'std::bind' makes a instance of 'std::function' within user-defined parameter.

You don't need to consider how does 'std::bind' work, just learn how to use it.

Anyway, let's have a look at examples.

#include <iostream>
#include <functional>

std::function<void()> func;

void no_arg()
{
  std::cout << "no_arg\n";
}

void int_arg(int i)
{
  std::cout << "int_arg " << i << std::endl;
}

class Foo
{
  public:
  void no_arg_method() {
    std::cout << "no_arg_method\n";
  }
};

int main()
{
  // func and no_arg are both take no arguments, so we can assign no_arg to func directry
  func = &no_arg;
  func();
  
  // int_arg takes one int argument, so we need to use std::bind to make new function object
  // with int_arg taking one argument of 10.
  func = std::bind(&int_arg, 10);
  func(); // no arguments provided here.
  
  // Foo::no__arg_method takes no arguments, but it needs implicit argument of 'this',
  // std::bind can bind instance address like this.
  Foo foo;
  func = std::bind(&Foo::no_arg_method, &foo);
  func(); // calls foo's no_arg_method

}
repl.it

And here is one more example, with function object taking arguments.

#include <iostream>
#include <functional>

std::function<void(int i)> func;

void int_arg(int i)
{
  std::cout << "int_arg " << i << std::endl;
}

void int_arg2(int i, int j)
{
  std::cout << "int_arg2 " << i << "/" << j << std::endl;
}

class Foo
{
  public:
  void int_arg_method(int i) {
    std::cout << "int_arg_method " << i << std::endl;
  }
};

int main()
{
  // func and no_arg are both take one int argument, so we can assign int_arg to func directry
  func = &int_arg;
  func(20); // call with argument;
  
  // int_arg2 takes two int argument, so we need to use std::bind to make new function object
  // with int_arg2 taking one argument(10 for instance).
  // std::placeholders::_1 means that 'will be replaced by first argument by caller' 
  func = std::bind(&int_arg2, 10, std::placeholders::_1);
  func(20); // std::placeholders::_1 is replaced to 20
  
  // also we can use placeholders with class method.
  Foo foo;
  func = std::bind(&Foo::int_arg_method, &foo, std::placeholders::_1);
  func(20);

}
repl.it


Tuesday, August 22, 2017

What is function object ?

std::function is a class for 'function object'.
This is powerful way to represent predicator.

Let's see how to use it.

First, I show a sample with no 'std::function's.

// Predicator class(i.e., has operator() ) which take int for argument and returns int by adding it's internal value.
class Adder
{
public:
    int to_add;
    int operator()(int a) {
        return a + to_add;
    }
};

// Another predicator doing multiply.
class Multiplier
{
public:
    int to_mul;
    int operator()(int a) {
        return a * to_mul;
    }
};

// Some class having std::vector<int>
class Foo
{
    std::vector<int> vec;
public:

    // apply predicator.
    template <typename T>
    void apply(T pred) {
        for(int& elm : vec) {
            elm = pred(elm);         //the predicator is intended to have 'int operator(int)'
        }
    }
};

// some function
void Bar(Foo& foo, int to_add, int to_mul)
{
    Adder adder;
    adder.to_add = to_add;
    foo.apply(adder);   // add for each int

    Multilier multi;
    multi.to_mul = to_mul;
    foo.apply(multi);   // mulply for each int
}

We need to declare predicator class for each calcuration( adding and multipling )
Next, let's do this using std::function.

// Some class having std::vector<int>
class Foo
{
    std::vector<int> vec;
public:

    // apply predicator.
    void apply(std::function<int(int)> func) {  //take std::function which take int as argument, and returns int.
        for(int& elm : vec) {
            elm = func(elm);      // call the func
        }
    }
};

int add(int a, int to_add) { return a+to_add; }
int mul(int a, int to_mul) { return a*to_mul; }

void Bar(Foo& foo, int to_add, int to_mul)
{
    //std::bind() makes std::function instance holding function pointer with internal values.
    //std::placeholders::_1 means the argument will passed by caller.

    std::function<int(int)> adder = std::bind(&add, std::placeholders::_1, to_add);
    //so, 'adder' has a pointer to function 'add' and a value 'to_add'.
    //first argument will be passed by the caller.

    foo.apply(adder);   // add 2 for each int

    //std::function to multiply.
    std::function<int(int)> multi = std::bind(&mul, std::placeholders::_1, to_mul);

    foo.apply(multi);   // mulply 3 for each int
}

std::function can have any value in it. and has operator() of specified type signature.
for example,
std::function<int(float)>  -  function object that take float for arugment, returns int.
std::function<std::string(double, int)>   - function object that take double and int, returnts std::string

Next, let's make this example shorter with lambda expression.

// Some class having std::vector
class Foo
{
    std::vector<int> vec;
public:

    // apply predicator.
    void apply(std::function<int(int)> func) {  //take std::function which take int as argument, and returns int.
        for(int& elm : vec) {
            elm = func(elm);      // call the func
        }
    }
};

void Bar(Foo& foo, int to_add, int to_mul)
{
    // lambda expression can make function object in line.
    std::function<int(int)> adder = [to_add](int a) -> int { return a+to_add; };

    foo.apply(adder);   // add 2 for each int

    std::function<int(int)> multi = [to_mul](int a) -> int { return a*to_mul; };

    foo.apply(multi);   // mulply 3 for each int
}

With std::function, we can easily declare predicator and make the program more flexible.







It&#39;s magic! std::bind

'std::bind' is a powerful helper for working around 'std::function'. 'std::bind' makes a instance of 'std::fun...