C + + method reference

Time:2021-5-4

C++ feels like a new language. ㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤ– Bjarne Stroustrup

Say ahead

Today’s title may not be too rigorous. Here I borrow the Java language. All friends who are familiar with Java should know the meaning of method referenceJava 8 in actionA piece of code in

inventory.sort(comparing(Apple::getWeight));

thereApple::getWeightThis is what we call method referenceAppleClassgetWeightPassed on tocomparing, passing the function as a first-class citizen.

  • Main topic

More precisely, how do we apply the member method to theSTLAlgorithmically? Let’s start with an example

struct Cell {
  explicit Cell(int value) : value_(value) {}
  int get_value() const { return value; }

 private:
   int value_;
};

application

std::vector<Cell> inputs = {Cell(3), Cell(10), Cell(113)};
std::vector<int> outputs;
  
std::transform(begin(inputs), end(inputs), back_inserter(outputs), Cell::get_value); //compile error!

We know that the above code can’t be compiled, so the problem is how to implement similar things in C + +.

Expensive solution STD:: function

We can use itC++2.0Introducedstd::functionSolve the above problem that cannot be compiled

std::transform(begin(inputs), end(inputs), std::back_inserter(outputs),
               std::function<int(const Cell&)>(&Cell::get_value));

std::functionAccept almost everything that can be called (free function, member function, static function, function object) and wrap it in a definitionoperator()Object that forwards the call to the wrapped callable object.
I’m not sure about itstd::functionAnd callable object readers can refer to my another article callable object.

Second best solution lambda

An easy way to do this is to wrap member functions inlambdain

std::transform(begin(inputs), end(inputs), back_inserter(outputs),
               [](const Cell& input) { return input.get_value(); });

It’s said herelambdaThe implementation of the expression is really simple, effective and correct. I think there is no problem in doing so. I say it is a suboptimal solution because a new variable is introduced.

The most suitable tool STD:: mem_ fn

For this example, the most suitable tool isstd::mem_fnIt’s too late. It isC++2.0After the introduction of, can replacestd::mem_funandstd::mem_fun_ref

std::transform(begin(inputs), end(inputs), back_inserter(outputs), std::mem_fn(&Cell::get_value));

The above description looks very similar to the java example in the beginning.
Here’s a brief introductionstd::mem_fnstd::mem_funandstd::mem_fun_ref

  • Introduction time

std::mem_fnAfter: C + + 11
std::mem_funandstd::mem_fun_ref: C + + 98 Standard

  • difference

std::mem_funIs the pointer version of the member function into a function object.
std::mem_fun_refIs the reference version of the member function into a function object.
std::mem_fnThen, both pointer and reference can convert a member function to a function object.

  • Header file

#include <functional>

Using range

C + + 20 introduces the concept of range library. Let’s see how to use it

auto outputs = inputs | ranges::view::transform(&Cell::get_value); // OK

Unfortunately, the current mainstreamC++The compiler does not support this writing. But readers can introduce itrange-v3, the usage is very simple, the above code does not need to modify, as long as therange-v3The header file is introduced into the project, and interested readers can study it by themselvesrange-v3This library.

Postscript

aboutrangeInterested readers can refer to this website ranges

Recommended Today

Large scale distributed storage system: Principle Analysis and architecture practice.pdf

Focus on “Java back end technology stack” Reply to “interview” for full interview information Distributed storage system, which stores data in multiple independent devices. Traditional network storage system uses centralized storage server to store all data. Storage server becomes the bottleneck of system performance and the focus of reliability and security, which can not meet […]