C++ 最大值超过c++;带函数调用的数组

C++ 最大值超过c++;带函数调用的数组,c++,C++,我有一个obj对象列表,每个对象都有一个eval()方法,返回一个double。我想得到所有这些的最大值。到目前为止,我一直在做 double maxval=std::numeric_limits::lowest(); 用于(常量自动和obj:objs){ maxval=std::max(maxval,obj->eval()); } 我想知道是否有一个更优雅的解决方案,您不必设置初始值-inf,类似于Python的 max_value=max(obj.eval()用于objs中的obj) 也

我有一个
obj
对象列表,每个对象都有一个
eval()
方法,返回一个
double
。我想得到所有这些的最大值。到目前为止,我一直在做

double maxval=std::numeric_limits::lowest();
用于(常量自动和obj:objs){
maxval=std::max(maxval,obj->eval());
}
我想知道是否有一个更优雅的解决方案,您不必设置初始值-inf,类似于Python的

max_value=max(obj.eval()用于objs中的obj)
也许吧。请注意,
eval()
可能很贵,因此我只想
eval()
obj
一次


有什么提示吗?可读性的奖励点。< /P> < P> C++相当于Python的代码> max < /C> >是./P>
auto-itr=std::max\u元素(
objs.begin(),objs.end(),
[](const auto&lhs,const auto&rhs){返回lhs.eval()
一些
好东西(仅限C++20):

但是请注意,正如@NathanOliver所指出的,这会调用
eval()
2N-2次。下面是一个自定义模板,它将调用
eval()
整整N次:

#include <optional>
#include <functional>
#include <type_traits>

template <class Range, class Cmp = std::less<>, class Proj = std::identity>
auto maxValue(const Range& rng, Cmp pred = Cmp{}, Proj p = Proj{})
{
    using std::begin;
    using std::end;
    using ValueType = std::remove_cvref_t<std::invoke_result_t<Proj,
        decltype(*begin(rng))>>;

    auto first = begin(rng);
    const auto last = end(rng);

    if (first == last)
        return std::optional<ValueType>{};

    auto result = std::invoke(p, *first);

    for (++first; first != last; ++first)
        result = std::max(std::invoke(p, *first), result, pred);

    return std::optional{result};
}

第二个和第三个参数具有合理的默认值,因此对于基元类型和类似的类型,可以忽略它们。

所以使用第一个参数的值的常规做法不适合您?为什么?@Yunnosch列表可能是空的。这会缓存
eval()
的结果吗?@NicoSchlömer我认为标准不需要缓存,所以它可能取决于标准库实现。它应该如何缓存结果?!这里没有涉及任何国家。它不能将结果写入全局变量,以便在下次调用时返回。我明白了。这是一个有趣的解决方案,但对我来说不是太有用
eval()
可能很昂贵,所以我真的只想对每个对象执行一次
eval()
。对每个
obj
调用
eval
的频率是多少?这是一个线性算法,所以每个对象执行一次。线性复杂度也可能意味着每个对象执行k次,例如,两次。这不是每个元素还需要两次调用
eval
?即,调用
e1 cmp e2
,然后调用
e2 cmp e3
。。。因此,只有第一个和最后一个元素对它们调用了一次
cmp
。看起来它被调用了
2N-2
次:
#include <ranges>

const auto maxval = std::ranges::max_element(objs, std::less<>{}, &ObjType::eval);

if (maxval != objs.cend())
    doStuffWith(*maxval);
if (!objs.empty()) ; // ...
#include <optional>
#include <functional>
#include <type_traits>

template <class Range, class Cmp = std::less<>, class Proj = std::identity>
auto maxValue(const Range& rng, Cmp pred = Cmp{}, Proj p = Proj{})
{
    using std::begin;
    using std::end;
    using ValueType = std::remove_cvref_t<std::invoke_result_t<Proj,
        decltype(*begin(rng))>>;

    auto first = begin(rng);
    const auto last = end(rng);

    if (first == last)
        return std::optional<ValueType>{};

    auto result = std::invoke(p, *first);

    for (++first; first != last; ++first)
        result = std::max(std::invoke(p, *first), result, pred);

    return std::optional{result};
}
const auto max = maxValue(myContainer, std::less<>{}, &Test::eval);