# `std::bind`¶

## Why? What’s The Problem?¶

Clumsy code like below …

• One-time functions, only used to do one stupid little thing (e.g. define `double distance_origin(Point p)` in terms of `double distance(Point p, Point q)`)

• Function definition in places which are far off their call sites ⟶ readability suffers!

## Sample Program: All Done Manually¶

```#include <cmath>
#include <iostream>

struct Point
{
Point(double x, double y)
: x(x), y(y) {}
double x, y;
};

double distance(Point p, Point q)
{
return std::sqrt(
std::pow(std::abs(p.x-q.x), 2) +
std::pow(std::abs(p.y-q.y), 2)
);
}

double distance_origin(Point p)
{
return distance(p, {0,0});
}

int main()
{
Point points[]{{1,2}, {3,4}, {5,6}};
double origin_distances[sizeof(points)/sizeof(Point)];

// compute origin-distances of points
int i=0;
for (auto p: points)
origin_distances[i++] = distance_origin(p);

for (double dist: origin_distances)
std::cout << dist << std::endl;

return 0;
}
```

## Sideway: `std::transform`¶

• Problem: manual loops to transform an array (or any container) into something else

• Loop body contains transformation code

• ⟶ cries for duplicate code elimination (here: using std::transform

• ⟶ similar pattern across `<algorithm>` (see here)

• Sorting criteria: `std::sort`, `std::map`, …

• Predicates: `std::find_if`, `std::equal`, …

• Arbitrary adaptations where helper functions are needed

## Sample Program: Using `std::transform`¶

Still using the one-time function `double distance_origin(Point p)` though …

```#include <cmath>
#include <iostream>
#include <algorithm>

struct Point
{
Point(double x, double y)
: x(x), y(y) {}
double x, y;
};

double distance(Point p, Point q)
{
return std::sqrt(
std::pow(std::abs(p.x-q.x), 2) +
std::pow(std::abs(p.y-q.y), 2)
);
}

double distance_origin(Point p)
{
return distance(p, {0,0});
}

int main()
{
Point points[]{{1,2}, {3,4}, {5,6}};
double origin_distances[sizeof(points)/sizeof(Point)];

// compute origin-distances of points
std::transform(points, points+sizeof(points)/sizeof(Point), origin_distances, distance_origin);

for (double dist: origin_distances)
std::cout << dist << std::endl;

return 0;
}
```

## `std::bind`: Null Adaptation, Pointlessly¶

```#include <gtest/gtest.h>
#include <functional>

static int void_function()
{
return 42;
}

TEST(bind_suite, plain_void_function)
{
auto func = std::bind(void_function);
ASSERT_EQ(func(), 42);
}
```

## `std::bind`: Adapting One Parameter To No Parameter¶

```#include <gtest/gtest.h>
#include <functional>

static int one_parameter_function(int i)
{
return i*2;
}

TEST(bind_suite, plain_one_parameter_function)
{
auto func = std::bind(one_parameter_function, 1);
ASSERT_EQ(func(), 2);
}
```

## `std::bind`: Hardcoding Parameters¶

```#include <gtest/gtest.h>
#include <functional>

static int minus(int i, int j)
{
return i-j;
}

TEST(bind_suite, minus_hardcoded)
{
auto _1_minus_2 = std::bind(minus, 1, 2);
ASSERT_EQ(_1_minus_2(), -1);
}
```

## `std::bind`: Swapping Parameters ⟶ `std::placeholders`¶

```#include <gtest/gtest.h>
#include <functional>

static int minus(int i, int j)
{
return i-j;
}

TEST(bind_suite, minus_swap_parameters)
{
auto second_minus_first = std::bind(minus, std::placeholders::_2, std::placeholders::_1);
ASSERT_EQ(second_minus_first(1, 2), 1);
}
```

## `std::bind`: Hardcoding Only First Parameter ⟶ `std::placeholders`¶

```#include <gtest/gtest.h>
#include <functional>

static int minus(int i, int j)
{
return i-j;
}

TEST(bind_suite, minus_hardcode_first_parameter)
{
auto _42_minus_param = std::bind(minus, 42, std::placeholders::_1);
ASSERT_EQ(_42_minus_param(1), 41);
}
```

## `std::bind`: Functor (Is-A Callable)¶

```#include <functional>
#include <gtest/gtest.h>

class Functor
{
public:
Functor(int i) : _i{i} {}
{
}

private:
int _i;
};

TEST(bind_suite, functor)
{
Functor func{42};
auto funcfunc = std::bind(func, 1);
ASSERT_EQ(funcfunc(), 43);
}
```

## `std::bind`: Lambda (Is-A Callable)¶

```#include <functional>
#include <gtest/gtest.h>

TEST(bind_suite, lambda)
{
auto func = [val=42](int i){ return val+i; };
auto funcfunc = std::bind(func, 1);
ASSERT_EQ(funcfunc(), 43);
}
```

## Sample Program: Using `std::transform` With `std::bind`¶

See how we can eliminate the one-time function ```double distance_origin(Point p)```

```#include <cmath>
#include <iostream>
#include <algorithm>
#include <functional>

struct Point
{
Point(double x, double y)
: x(x), y(y) {}
double x, y;
};

double distance(Point p, Point q)
{
return std::sqrt(
std::pow(std::abs(p.x-q.x), 2) +
std::pow(std::abs(p.y-q.y), 2)
);
}

int main()
{
Point points[]{{1,2}, {3,4}, {5,6}};
double origin_distances[sizeof(points)/sizeof(Point)];

// compute origin-distances of points
std::transform(points, points+sizeof(points)/sizeof(Point), origin_distances,
std::bind(distance, std::placeholders::_1, Point{0,0}));

for (double dist: origin_distances)
std::cout << dist << std::endl;

return 0;
}
```

## Summary¶

• Have to get used to `std::bind`

• Goal is to have no runtime overhead

• Late binding (polymorphism) ruled out

• ⟶ No common base class

• Only the call signatures (parameter and return types) are the same

• If you want to define interfaces (i.e. share a type), use std::function

What does this mean?

• Perfect for `<algorithm>` which is also designed for speed

• Have to be careful when code size is important

• Client code has to be instantiated with the type

• Tradeoff: speed, code size, elegance, design, taste …

And Lambdas?

• Lambdas are usually a better alternative