2016-04-07 33 views
2

多数の倍精度配列を扱いたいと思います。すべての配列の長さは同じです。 std :: arraysのstd :: vectorを使うことにしました。データのスケーリングのために、私はすべての値の最小値と最大値を見つける必要があります。どのように私がこれを行うことができたかは次の通りです: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<N>をインスタンス化するために使用する非型パラメータが定数式ではないためです。

私の理解では、コンパイラはコンパイル時にインスタンス化するバージョンを知ることはできませんが、この場合はかなり明らかです。私がやったことは、for-loopを手動でアンロールすることでしたが、それは醜いです。これを達成するにはより美的な方法をお勧めしますか?

答えて

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アルゴリズムは、関数ポインタを消費するように呼び出し可能オブジェクトを簡単に消費します。

0123,を書き直すと少し迷惑です。我々は、インラインそれを移動することができます。問題の種類が巨大であるため、右が少し冗長です

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では、私たちは離れて、それらの膨大な種類とやるとget:自動的に参照することによりiをキャプチャテンプレートoperator()で呼び出し可能なオブジェクトを作成します

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

を。

私は通常、投影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]; 
    } 
} 
+0

ニース書き込みを-アップ。最初の文章であなたが質問に答えたことを考慮して、あなたは上を行きました。個人的に私は 'order_by'の前にそれを置いていたでしょうが、それはやや良い感じです。 – vu1p3n0x

関連する問題