So I have been looking into using abstracted algorithms to reuse reoccurring patterns in my code. Specifically, I want to determine the the element in an array of nodes that has the highest 'score', determined by evaluation of a complex scoring member function.
After some help I've come up with (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;
}
So consider my Node 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));
}
};
and my array of nodes:
std::array<Node, 100000> nodes;
I can call
auto const& Node = *std::max_eval_element(std::cbegin(nodes), std::cend(nodes), std::mem_fn(&Node::Score1));
but now I want to repeat this for Score2
, where the input depends on some local variable... of course I can write some lambda function... but we have std::bind
for that, right? I know you can cal bind on a member function like
std::bind(this, std::mem_fn(Node::Score1));
But what I want is the other way around. Which doesn't work.
auto const& Node = *std::max_eval_element(std::cbegin(nodes), std::cend(nodes), std::bind(std::mem_fn(&Node::Score2), 1.0));
I tried it the other way around, but that also doesn't work
auto const& Node = *std::max_eval_element(std::cbegin(nodes), std::cend(nodes), std::mem_fn(std::bind(&Node::Score2), 1.0));
I know why this doesn't work... a member function requires the object pointer as a (hidden) first argument. But that would mean we are missing something like std::bind_mem_fn
or so... We had std::bind2nd
in the past, but it has been removed in C++17...
Again: of course I can use a lambda, but considering things like std:mem_fn
and std::bind
exist, and abstracted algorithms is a good thing...
Am I missing something, Or is this just missing from the standard?