【问题标题】:Comparison function for std::vector of std::arraysstd::arrays 的 std::vector 的比较函数
【发布时间】:2016-07-28 01:47:05
【问题描述】:

我想处理大量的双精度数组。所有数组的长度相同。我决定使用 std::arrays 的 std::vector。对于数据缩放,我需要找到所有值的最小值和最大值。我如何认为我可以做到这一点如下:

#include <algorithm>
#include <vector>
#include <array>

class ChannelData {
...
template<std::size_t N>
bool static compareX(std::array<double, m_nelem> const& a, std::array<double, m_nelem> const& b) {
    return a[N] < b[N];
}

std::vector<std::array<double, m_nelem> > m_data;
std::array<<std::array<double, 2> m_nelem> m_minmax;

void find_minmax_x(){
    for (int i = 0; i < m_nelem; i++){
        auto minmax = std::minmax_element(m_data.begin(), m_data.end(), compareX<i>);
        m_minmax[i][0] = (*minmax.first)[i];
        m_minmax[i][1] = (*minmax.second)[i];
    }
}

这不会编译。那是因为我用来在函数find_minmax_x 中实例化compareX&lt;N&gt; 的非类型参数i 不是常量表达式。

据我了解,编译器不知道在编译时要实例化哪些版本,尽管在这种情况下很明显。我最终做的是手动展开 for 循环,但这很难看。你能推荐一种更美观的方式来实现这一点吗?

【问题讨论】:

    标签: arrays templates c++11 vector std


    【解决方案1】:
    struct compareX {
      std::size_t N;
      bool operator()(std::array<double, m_nelem> const& a, std::array<double, m_nelem> const& b) const {
        return a[N] < b[N];
      }
    };
    

    ...

    void find_minmax_x(){
      for (int i = 0; i < m_nelem; i++){
        auto minmax = std::minmax_element(m_data.begin(), m_data.end(), compareX{i});
        m_minmax[i][0] = (*minmax.first)[i];
        m_minmax[i][1] = (*minmax.second)[i];
      }
    }
    

    如果您的值不是编译时值,请不要将其作为模板非类型参数传递。存储它。

    std 算法将像使用函数指针一样轻松地使用可调用对象。

    写出compareX 有点烦人。我们可以内联移动它:

    void find_minmax_x(){
      for (int i = 0; i < m_nelem; i++){
        auto compareX = [i](std::array<double, m_nelem> const& a, std::array<double, m_nelem> const& b) {
          return a[i] < b[i];
        };
        auto minmax = std::minmax_element(m_data.begin(), m_data.end(), compareX);
        m_minmax[i][0] = (*minmax.first)[i];
        m_minmax[i][1] = (*minmax.second)[i];
      }
    }
    

    那里有点冗长,因为所讨论的类型很大。在 C++14 中,我们取消了那些巨大的类型并得到:

    void find_minmax_x(){
      for (int i = 0; i < m_nelem; i++){
        auto compareX = [&](auto&& a, auto&& b) {
          return a[i] < b[i];
        };
        auto minmax = std::minmax_element(m_data.begin(), m_data.end(), compareX);
        m_minmax[i][0] = (*minmax.first)[i];
        m_minmax[i][1] = (*minmax.second)[i];
      }
    }
    

    它使用模板operator() 自动创建一个可调用对象,该模板通过引用捕获i

    我通常有一个投影order_by比较:

    template<class F, class O=std::less<>>
    auto order_by( F&& f, O&& o = {} ) {
      return [f = std::forward<F>(f), o = std::forward<O>(o)](auto&& lhs, auto&& rhs)->bool{
        return o(f(lhs), f(rhs));
      };
    };
    

    (又是 C++14,可以用 C++11 编写)这会将您的代码简化为:

    void find_minmax_x(){
      for (int i = 0; i < m_nelem; i++){
        auto minmax = std::minmax_element(
          m_data.begin(), m_data.end(), 
          order_by([i](auto&&a){return a[i];})
        );
        m_minmax[i][0] = (*minmax.first)[i];
        m_minmax[i][1] = (*minmax.second)[i];
      }
    }
    

    【讨论】:

    • 不错的文章。考虑到您在第一句话中回答了问题,您已经超越了。就我个人而言,我会在 order_by 之前离开它,但它确实读起来稍微好一些。
    猜你喜欢
    • 1970-01-01
    • 2012-02-05
    • 1970-01-01
    • 2021-01-21
    • 2020-03-06
    • 2013-08-29
    • 2015-03-04
    • 1970-01-01
    • 2019-04-23
    相关资源
    最近更新 更多