0

floatのようなスカラー型でも動作するカスタムデータ型に対して、特殊な「最大」(つまり最大)関数を実装する方法に関するアドバイスを探しています。私が書いているデータ型はベクトルのラッパーです(最終的にはstd::vectorではなく4つの浮動小数点数のSIMDベクトルです)。そして、2つのベクトルを比較し、各要素の最大値である新しいベクトルを返すmax関数を提供します。 。これは比較演算子を使用するstd::maxとは異なりますが、概念は同じです。C + +の比較演算子をオーバーロードせずにstd :: maxのカスタム型を特化する方法?

問題は、入力にmaxを適用するdo_max(T x, T y)という汎用関数があることです。スカラーフロート入力(例えば、do_max<float>(0.1f, 0.2f)私のベクトルクラス(例えば、do_max<MyVector>(v0, v1))の両方で機能するにはこの関数が必要です。

MyVectorの比較演算子のオーバーロードは、まったく異なるSIMD組み込み関数を使用しているため、オプションではないことに注意してください。ブール値を返すのではなく、要素比較ごとに1,0、-1の整数ベクトルを作成します結果。

// compile with: g++ -std=c++11 max.cc -o max 
#include <algorithm> 
#include <vector> 

class MyVector { 
public: 
    MyVector(float x0, float x1, float x2, float x3) : storage_ { x0, x1, x2, x3 } {}; 

    friend MyVector max(MyVector lhs, const MyVector & rhs); 

private: 
    std::vector<float> storage_; 
}; 

MyVector max(MyVector lhs, const MyVector & rhs) { 
    for (size_t i = 0; i < lhs.storage_.size(); ++i) { 
    lhs.storage_[i] = std::max(lhs.storage_[i], rhs.storage_[i]); 
    } 
    return lhs; 
} 

template<typename T> 
T do_max(const T & x, const T & y) { 
    // if this is std::max then it won't compile for MyVector 
    return max(x, y); 
} 

int main(int argc, char * argv[]) { 

    MyVector v0 { 0.1, 0.2, 0.3, 0.4 }; 
    MyVector v1 { 0.4, 0.3, 0.2, 0.1 }; 

    MyVector v2 = do_max(v0, v1); 

    // Comment out the following line to successfully compile. 
    // However I'd like this to work for scalar types too: 
    float f0 = do_max(0.1f, 0.2f); 

    return 0; 
} 
私はスカラー型のため std::maxにその max機能の決意を作成する方法を必要と感じている

、そして私の専門の:あなたはfloat f0 = ...行をコメントアウトしない限り、

私は以下の持っているコードはコンパイルされません。 max MyVectorタイプのフレンド機能。

このように機能するmax関数を定義するにはどうすればよいですか? std::maxを忘れて、MyVectorに特化した独自のmax関数を使用し、floatのようなスカラー型の実装も提供していますか?

これは、私がMyVectorとスカラーの両方の型(コンパイル時にパラメータ化された型として)で動作することを望むデータパスを実装しているという背景があります。私はすでに算術演算を行っていますが、maxの解はmin,exppowのような他の関数でも使われます。

答えて

7

クラシックソリューション:

template<typename T> 
T do_max(const T & x, const T & y) { 
    using std::max; 
    return max(x, y); 
} 

引数依存ルックアップがfloatのために、これは発生しません、あなたはstd::max<float>を取得し、あなたのmax見つけました。

+0

ありがとうございます、私の例のために動作します。 – meowsqueak

+0

'return max(x、y)'を 'return max (x、y)'に置き換えると、なぜ失敗するのか知っていますか?この場合、コンパイラは 'std :: max (x、y)'の呼び出しとしてそれを解決し、 'do_max 'がインスタンス化されたときに '<'演算子に無効なオペランドで失敗するように見えます。 'max'で明示的に型パラメータを設定すると、なぜこの動作が変わるのか理解できません。 – meowsqueak

+1

あなたの関数はテンプレートではありませんか? max は、明示的なテンプレートのインスタンス化です。 – MSalters

関連する問題