std :: array的std :: vector的比较函数

时间:2016-04-07 09:19:28

标签: arrays templates c++11 vector std

我想处理大量的双打数组。所有阵列的长度都相同。我决定使用std :: vector的std :: arrays。对于数据缩放,我需要找到所有值的最小值和最大值。我怎么想我能做到这一点如下:

#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];
    }
}

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

根据我的理解,编译器不知道在编译时要实例化哪个版本,即使在这种情况下它是相当明显的。我最终做的是手动展开for循环,但这很难看。你能推荐一种更美观的方式来实现这个目标吗?

1 个答案:

答案 0 :(得分:4)

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];
  }
}