![](/img/trans.png)
[英]What does std::_Bind<std::_Mem_fn<void (ClassName::*)()>(ClassName*)> mean? (C++)
[英]C++ std::mem_fn and std::bind the other way around
所以我一直在研究使用抽象算法在我的代碼中重用重復出現的模式。 具體來說,我想確定節點數組中具有最高“分數”的元素,該元素是通過對復雜評分成員 function 的評估來確定的。
經過一些幫助,我想出了(C++ 17)
template <typename FwdIt, typename Eval, typename Pred = std::less<>>
constexpr FwdIt max_eval_element(FwdIt first, FwdIt last, Eval eval, Pred pred = Pred()) {
FwdIt found = first;
if (first != last) {
auto best = eval(*found);
while (++first != last) {
if (auto const thisVal = eval(*first);
pred(best, thisVal)) {
found = first;
best = thisVal;
}
}
}
return found;
}
所以考慮我的節點 class:
class Node {
private:
double val;
public:
Node(double val) noexcept : val(val) {}
[[nodiscard]] auto Score1() const noexcept {
return std::sqrt(std::log(10.0 / val));
}
[[nodiscard]] auto Score2(double other) const noexcept {
return std::sqrt(std::log(other / val));
}
};
和我的節點數組:
std::array<Node, 100000> nodes;
我可以打電話
auto const& Node = *std::max_eval_element(std::cbegin(nodes), std::cend(nodes), std::mem_fn(&Node::Score1));
但現在我想對Score2
重復這個,其中輸入取決於一些局部變量......當然我可以寫一些 lambda function ......但我們有std::bind
,對吧? 我知道你可以在成員 function 上綁定
std::bind(this, std::mem_fn(Node::Score1));
但我想要的恰恰相反。 這是行不通的。
auto const& Node = *std::max_eval_element(std::cbegin(nodes), std::cend(nodes), std::bind(std::mem_fn(&Node::Score2), 1.0));
我嘗試了相反的方法,但這也不起作用
auto const& Node = *std::max_eval_element(std::cbegin(nodes), std::cend(nodes), std::mem_fn(std::bind(&Node::Score2), 1.0));
我知道為什么這不起作用...成員 function 需要 object 指針作為(隱藏的)第一個參數。 但這意味着我們缺少諸如std::bind_mem_fn
之類的東西......我們過去有std::bind2nd
,但它已在 C++17 中刪除......
再說一遍:當然我可以使用 lambda,但是考慮到std:mem_fn
和std::bind
之類的東西存在,抽象算法是一件好事……
我是否遺漏了什么,或者這只是標准中遺漏的?
調用std::bind(&Node::Score2)
是問題所在。 它缺少 arguments 傳遞給Score2
。 你要:
std::bind(&Node::Score2, std::placeholders::_1, 1.0)
這不是指向成員的指針,因此它不是std::mem_fn
的適當參數
或者,您可以使用 lambda
[](const auto & node) { return node.Score2(1.0); }
我得出的結論是 lambda 的優化優於 std::mem_fn
拿這個代碼:
#include <iostream>
#include <array>
#include <functional>
class Node {
private:
double val;
public:
Node(double val) noexcept : val(val) {}
[[nodiscard]] auto Score() const noexcept {
return 10.0 / val;
}
};
template <typename FwdIt, typename Eval, typename Pred = std::less<>>
constexpr FwdIt max_eval_element(FwdIt first, FwdIt last, Eval eval, Pred pred = Pred()) {
FwdIt found = first;
if (first != last) {
auto best = eval(*found);
while (++first != last) {
if (auto const thisVal = eval(*first);
pred(best, thisVal)) {
found = first;
best = thisVal;
}
}
}
return found;
}
int main()
{
std::array<Node, 10> nodes{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
auto nodeIt1 = max_eval_element(std::cbegin(nodes), std::cend(nodes), std::mem_fn(&Node::Score));
std::cout << "dist1 " << std::distance(std::cbegin(nodes), nodeIt1) << std::endl;
auto nodeIt2 = max_eval_element(std::cbegin(nodes), std::cend(nodes), [](Node const& node) { return node.Score(); });
std::cout << "dist2 " << std::distance(std::cbegin(nodes), nodeIt2) << std::endl;
}
如果您查看已編譯的程序集(例如在 GodBolt 上,使用 -O2 ),則 std:mem_fn 結果是 function 調用
42 movsd QWORD PTR [rsp+8], xmm1
43 call Node::Score() const
44 movsd xmm1, QWORD PTR [rsp+8]
,而 lambda 是內聯的
69 movsd xmm1, QWORD PTR .LC0[rip]
70 divsd xmm1, QWORD PTR [rax]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.