Skip navigation

Monthly Archives: March 2024

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <list>
#include <numeric>
#include <algorithm>
#include <iterator>
#include <functional>
#include <random>

using std::function;

void f( int n1, int n2 ) {
printf( "%d %d\n", n1, n2 );
}

int main() {
{
// Make a function object that you can invoke, to wind up calling some plain C-style function.
// This kind of use of std::bind may have limited use, but you could use it this way to switch-up
// the function that is running using a std::function variable (instead of using something like a switch statement)
//
// That way, the lambda acts like a function pointer (the function to be run is selected once)
std::function<void (int, int)> funcObj = std::bind( f, std::placeholders::_1, std::placeholders::_2 );
funcObj( 1, 2 ); // Equivalent to calling f( 1, 2 )
}

{
// Here, the data a, b is available as locals. You don't want to cache a,b as global data
// to feed into the function f later, so you just capture them using std::bind or a lambda
//
// So here, we're going to use std::bind to stick two existing variables to a function object.
// This is 100% eq to using a lambda, as shown below this one
int a = 5, b = 6;
std::function<void ()> funcObj = std::bind( f, a, b );
funcObj(); // Equivalent to calling f( a, b )

// Lambda capture formulation eq to above std::bind call
funcObj = [a, b]() {
f(a, b);
};
funcObj();
}

{
// You might say std::bind can be a little bit too flexible!!
// Apparently not all your std::bind use has to be completely sensible
int a = 5, b = 6;
std::function<void (float, float, float, float)> funcObj = std::bind( f, a, b );
funcObj(1.f, 2.f, 3.f, 4.f); // Still equivalent to calling f( 5, 6 )
// All the float args are ignored.
}

{
// You can use std::placeholders to leave an argument open to the lambda
std::function<void (int)> funcObj = std::bind( f, 99, std::placeholders::_1 );
funcObj( 20 ); // Equivalent to calling f( 99, 20 )

// raw lambda eq
funcObj = [ x = 99 ]( int a ) {
f( x, a );
};
funcObj( 20 );
}

// POINTER TO MEMBER FUNCTION:
{
struct A {
void go( int n1 ) {
printf( "%d\n", n1 );
}

int i = 2;
};

// You can also bind a function object to invoke a function to run on an instance of a class.
// This creates a major danger of dangling pointers if you make a mistake.
A a;
int v = 100;
std::function<void ()> funcObj = std::bind(
&A::go, // Pointer to member function to call
&a, // Instance of class to call member function on
v // value for argument to function
);
funcObj();

// lambda eq
funcObj = [v, &a]() {
a.go( v );
};
funcObj();
}

// Without std::function: pointer to member function:
{
// This is what it would look like to bind a pointer to a member function without std::function:
struct C {
void f() { puts( "C::f()" ); }
};

void (C::*memberFunctionPointerVariableName)() = &C::f;
C c;
(c.*memberFunctionPointerVariableName)();

// Lambda using a pointer to a member function
std::function<void ()> funcObj = std::bind(
&C::f, // Pointer to member function to call
&c // Instance of class to call member function on
);
funcObj();
}


// There's also pointers to members, and std::mem_fn for pointing to a data member!
}