简体   繁体   English

如何使std :: pop_heap接受适当的函数指针作为比较?

[英]How to make appropriate function pointer accepted by std::pop_heap as Compare?

I have a Node class with the functions 我有一个带有这些函数的Node类

static bool HasGreaterF(const Node& a, const Node& b);
static bool HasGreaterF(const std::shared_ptr<Node>& a, const std::shared_ptr<Node>& b);

Then I make a vector as heap and would like to use the second function as Compare. 然后我将一个向量作为堆,并希望使用第二个函数作为比较。 This doesn't work, because the function pointer can't get matched to one function. 这不起作用,因为函数指针无法与一个函数匹配。 If I delete the first function it works. 如果我删除它的第一个功能。 How to make it work with both functions? 如何使它兼具两种功能?

std::vector<std::shared_ptr<Node>> openlist_min_f;
std::pop_heap(openlist_min_f.begin(), openlist_min_f.end(), &Node::HasGreaterF);

Use static_cast to specify it: 使用static_cast指定它:

std::pop_heap(openlist_min_f.begin(), openlist_min_f.end(), 
              static_cast<bool (*)(const std::shared_ptr<Node>&, const std::shared_ptr<Node>&)>
              (&Node::HasGreaterF));

Or use a lambda wrapper as @David suggested, since the functions should not be ambiguous in this case. 或者使用@David建议的lambda包装器,因为在这种情况下函数不应该是模糊的。

std::pop_heap(openlist_min_f.begin(), openlist_min_f.end(), 
              [](const auto& l, const auto& r){ return Node::HasGreaterF(l, r); });

The reason you can't use it as-is is that pop_heap has to deduce the type of the comparator you pass in, and an overloaded function doesn't have one type. 你不能原样使用它的原因是pop_heap必须推断你传入的比较器的类型,而重载的函数没有一种类型。 There's contexts in which you can use the name of an overloaded function outside of simply calling them, but passing as an argument to a function template isn't one them. 在上下文中你可以使用重载函数的名称而不是简单地调用它们,但是作为参数传递给函数模板不是它们之一。 In this case, you have to explicitly state which HasGreaterF you mean. 在这种情况下,你必须明确地说明 HasGreaterF你的意思。

You can either use a static_cast (as mentioned) or just wrap it in a lambda: 您既可以使用static_cast (如上所述),也可以将其包装在lambda中:

std::pop_heap(openlist_min_f.begin(), openlist_min_f.end(),
    [](const auto& lhs, const auto& rhs) { return Node::HasGreaterF(lhs, rhs); });

The lambda has the advantage in that it has a greater likelihood of being inlined in my experience (though both are despressingly verbose). lambda的优势在于它更有可能在我的经验中被内联(虽然两者都是令人厌恶的冗长)。 You can always macro-ify the lambda wrapping in C++14: 你总是可以在C ++ 14中使用lambda包装:

#define WRAP_FUN(f) [](auto&&... args) -> decltype(auto) { return f(std::forward<decltype(args)>(args)...); }

so that this becomes: 这样就变成了:

std::pop_heap(openlist_min_f.begin(), openlist_min_f.end(), WRAP_FUN(Node::HasGreaterF));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM