C++ 方法引用

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

說在前面

今天的標題可能不太嚴謹,這裏我借用了Java語言中的說法,熟悉Java的朋友應該都知道方法引用的含義,這裏引入Java 8 in action中的一段代碼c++

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

這裏的Apple::getWeight就是咱們說的方法引用,這裏能夠理解爲咱們將Apple類的方法getWeight傳遞給了comparing,將函數做爲一等公民進行傳遞。git

  • 正題

更準確地說,咱們如何將成員方法應用到STL算法上?先看一個例子github

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

 private:
   int value_;
};

應用算法

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!

咱們知道上面的代碼是沒法經過編譯的,那麼問題來了,在C++中怎麼實現相似的東西。函數

昂貴的解決方案 std::function

咱們可使用C++2.0引入的std::function解決上述沒法經過編譯的問題工具

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

std::function接受幾乎全部可調用的東西(自由函數,成員函數,靜態函數,函數對象),並將其包裝在定義一個operator()的對象中,該對象將調用轉發給包裝的可調用對象。
對於不太清楚std::function和可調用對象的讀者能夠參考個人另一篇文章可調用對象網站

次優的解決方案 lambda

一種簡單的方法就是將成員函數包裝在lambda指針

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

這裏說lambda表達式的實現確實簡單有效,並且正確,我的認爲這麼去作是沒有任何問題的,說它是次優解是由於引入了一個新的變量。code

最適合的工具 std::mem_fn

針對本例,最適合的工具就是std::mem_fn了。它是C++2.0以後引入的,能夠取代std::mem_funstd::mem_fun_reform

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

上述的寫法看起來跟開篇將到的Java的例子就很相似了。
簡單介紹一下std::mem_fnstd::mem_funstd::mem_fun_ref

  • 引入時間

std::mem_fn:C++11之後
std::mem_funstd::mem_fun_ref:C++98標準

  • 區別

std::mem_fun是指針版的把成員函數轉換成函數對象。
std::mem_fun_ref是引用版的把成員函數轉換成函數對象。
std::mem_fn則是不管指針仍是引用均可以把成員函數轉換爲函數對象。

  • 頭文件

#include <functional>

使用 range

C++20引入了range庫的概念,咱們看看怎麼用

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

不過遺憾的是,目前主流的C++編譯器還不支持這種寫法。不過讀者能夠引入range-v3,用法很是簡單,上面的代碼不用修改,只要將range-v3的頭文件引入到工程中去,有興趣的讀者能夠自行去研究range-v3這個庫。

後記

對於range有興趣的讀者能夠參考這個網站ranges

相關文章
相關標籤/搜索