The function template std::memfn generates wrapper instances designed to store, duplicate, and execute pointers to different members. When calling a std::memfn, we have the option to utilize either references or pointers (including smart pointers) to an object.
The C++ Standard Library features the header that encompasses the function adapter std::memfunref. This adapter, part of the function adapters group along with std::memfun and std::memfn, aims to adapt member functions for utilization in function objects and algorithms. By employing std::memfunref, you can generate function objects capable of invoking a specified member function on instances of a specific class. Unlike std::memfun that accepts pointers, std::memfun_ref necessitates a reference to the object. This distinction proves valuable, especially in scenarios where there is a collection of objects, and applying a member function uniformly to each object is desired.
Syntax:
It has the following syntax:
template< class Res, class T, class Arg >
std::const_mem_fun1_ref_t<Res,T,Arg> mem_fun_ref( Res (T::*f)(Arg) const );
Example 1:
Let's consider a scenario to demonstrate the functionality of the std::memfunref method in C++.
#include <functional>
#include <iostream>
#include <memory>
struct Foo
{
void say_hello()
{
std::cout << "Greetings from Foo!\n";
}
void print_value(int value)
{
std::cout << "Value: " << value << '\n';
}
int add_numbers(int x, int y)
{
return x + y;
}
template<typename... Args> int sum_all(Args... args)
{
return (args + ...);
}
auto calculate_sum(auto... args) // C++20 required
{
return (args + ...);
}
int data = 100;
};
int main()
{
auto obj = Foo{};
auto greet = std::mem_fn(&Foo::say_hello);
greet(obj);
auto print = std::mem_fn(&Foo::print_value);
print(obj, 42);
auto access_data = std::mem_fn(&Foo::data);
std::cout << "Data: " << access_data(obj) << '\n';
auto add = std::mem_fn(&Foo::add_numbers);
std::cout << "Sum: " << add(obj, 5, 7) << '\n';
auto ptr = std::make_unique<Foo>();
std::cout << "Accessed Data: " << access_data(ptr) << '\n';
std::cout << "Sum with Pointer: " << add(ptr, 10, 20) << '\n';
auto sum_fn = std::mem_fn(&Foo::sum_all<short, int, long>);
std::cout << "Sum of All: " << sum_fn(ptr, 1, 2, 3) << '\n';
auto calc_sum = std::mem_fn(&Foo::calculate_sum<short, int, float, double>);
std::cout << "Calculated Sum: " << calc_sum(ptr, 5, 7, 10.0f, 13.0) << '\n';
}
Output:
Greetings from Foo!
Value: 42
Data: 100
Sum: 12
Accessed Data: 100
Sum with Pointer: 30
Sum of All: 6
Calculated Sum: 35
Example 2:
Let's consider another instance to demonstrate the functionality of the std::memfunref method in C++.
#include <iostream>
#include <algorithm>
#include <vector>
#include <functional>
class MyClass {
public:
MyClass(int val) : value(val) {}
// Member function to be adapted
void printValue() const {
std::cout << "Value: " << value << std::endl;
}
int getValue() const {
return value;
}
private:
int value;
};
int main() {
// Create instances of MyClass
std::vector<MyClass> vec;
vec.emplace_back(10);
vec.emplace_back(20);
vec.emplace_back(30);
// Use std::mem_fun_ref to adapt the member function printValue
std::for_each(vec.begin(), vec.end(), std::mem_fun_ref(&MyClass::printValue));
// Using std::mem_fun_ref to adapt member function returning int
auto getValue = std::mem_fun_ref(&MyClass::getValue);
std::vector<int> values;
std::transform(vec.begin(), vec.end(), std::back_inserter(values), getValue);
// Print the extracted values
std::cout << "Extracted Values:" << std::endl;
for (const auto& val : values) {
std::cout << val << " ";
}
std::cout << std::endl;
return 0;
}
Output:
Value: 10
Value: 20
Value: 30
Extracted Values:
10 20 30
Example 3:
Let's consider a different example to demonstrate the functionality of the std::memfunref method in the C++ programming language.
#include <iostream>
#include <vector>
#include <functional> // for std::mem_fun_ref
class Person {
private:
std::string name;
int age;
public:
Person(const std::string& n, int a) : name(n), age(a) {}
void greet() const {
std::cout << "Hello, I'm " << name << " and I'm " << age << " years old." << std::endl;
}
};
int main() {
std::vector<Person> people;
people.push_back(Person("Alice", 30));
people.push_back(Person("Bob", 25));
people.push_back(Person("Charlie", 40));
// Create a mem_fun_ref function object for Person::greet
auto greetFunc = std::mem_fun_ref(&Person::greet);
// Call the greet function on each person in the vector
for (const auto& person : people) {
greetFunc(person);
}
return 0;
}
Output:
Hello, I'm Alice and I'm 30 years old.
Hello, I'm Bob and I'm 25 years old.
Hello, I'm Charlie and I'm 40 years old.
Conclusion:
To summarize, in C++, leverage the versatile function adapter std::memfunref from the C++ Standard Library to construct function objects capable of invoking specific member functions on instances of a specified class. This adapter proves beneficial when dealing with object containers since it operates with object references rather than pointers, unlike std::memfun. By encapsulating member function calls into function objects, std::memfun_ref enhances the readability and manageability of code, simplifying the utilization of member functions within generic algorithms or function objects. This tool streamlines working with object-oriented code in C++, providing enhanced flexibility and ease of use while maximizing the potential of the C++ Standard Library, resulting in cleaner and more expressive code.