CodeNebula
C++11stlintermediate

std::mem_fn (C++11 Addition)

C++11 · Modern Revolution · Compiler flag: -std=c++11

Explanation

Creates a callable wrapper from a pointer to a member function, simplifying its use with standard algorithms and function objects.

Real-World Scenario

Call a member function on each element in a collection of objects using `std::for_each`.

Quick Snippet

snippet.cpp
#include <functional>
#include <vector>
#include <algorithm>
struct Widget { void activate() {} };
std::vector<Widget> widgets(5);
std::for_each(widgets.begin(), widgets.end(), std::mem_fn(&Widget::activate));

Full Example

mem_fn.cpp
// CodeNebula - C++11 Example: std::mem_fn
// Compile: g++ -std=c++11 -Wall -Wextra -o example mem_fn.cpp

// std::mem_fn creates a callable wrapper from a pointer to member
// function or data member. Unlike std::bind, it doesn't fix any
// arguments -- the object is passed at call time.

#include <iostream>
#include <functional>
#include <vector>
#include <algorithm>
#include <string>
#include <memory>

struct Employee {
    std::string name;
    int salary;

    void greet() const {
        std::cout << "Hi, I'm " << name << std::endl;
    }

    int bonus(int percent) const {
        return salary * percent / 100;
    }

    bool earns_more_than(int threshold) const {
        return salary > threshold;
    }
};

int main() {
    // Basic mem_fn with member function
    auto greet = std::mem_fn(&Employee::greet);
    Employee alice{"Alice", 80000};
    greet(alice);  // pass object as first argument

    // mem_fn with member function taking arguments
    auto bonus = std::mem_fn(&Employee::bonus);
    std::cout << "Alice 10% bonus: " << bonus(alice, 10) << std::endl;

    // Works with pointers too
    Employee* ptr = &alice;
    greet(ptr);
    std::cout << "Bonus via pointer: " << bonus(ptr, 15) << std::endl;

    // Works with smart pointers
    auto bob = std::make_shared<Employee>(Employee{"Bob", 95000});
    greet(bob);
    std::cout << "Bob 20% bonus: " << bonus(bob, 20) << std::endl;

    // Use mem_fn with algorithms
    std::vector<Employee> team = {
        {"Carol", 70000}, {"Dave", 90000}, {"Eve", 60000}
    };

    std::cout << "\nTeam greetings:" << std::endl;
    std::for_each(team.begin(), team.end(), std::mem_fn(&Employee::greet));

    // mem_fn with data members (accesses the member directly)
    auto get_name = std::mem_fn(&Employee::name);
    auto get_salary = std::mem_fn(&Employee::salary);
    std::cout << "\nTeam salaries:" << std::endl;
    for (const auto& e : team) {
        std::cout << "  " << get_name(e) << ": $" << get_salary(e) << std::endl;
    }

    // Use mem_fn in count_if
    auto earns_more = std::mem_fn(&Employee::earns_more_than);
    long count = std::count_if(team.begin(), team.end(),
        [&earns_more](const Employee& e) { return earns_more(e, 65000); });
    std::cout << "\nEmployees earning > $65000: " << count << std::endl;

    return 0;
}

// Expected output:
// Hi, I'm Alice
// Alice 10% bonus: 8000
// Hi, I'm Alice
// Bonus via pointer: 12000
// Hi, I'm Bob
// Bob 20% bonus: 19000
//
// Team greetings:
// Hi, I'm Carol
// Hi, I'm Dave
// Hi, I'm Eve
//
// Team salaries:
//   Carol: $70000
//   Dave: $90000
//   Eve: $60000
//
// Employees earning > $65000: 2
Run command
g++ -std=c++11 -Wall -Wextra -o example mem_fn.cpp