2017-12-04 11 views
2

テンプレートの関数にテンプレートのパラメータとして関数std::maxを渡そうとしていますが、何らかの理由でコンパイラが関数の型を推測できないというエラーを出力します。簡単な例では同じ問題が再現されます。それは自分のmax2機能で動作しますが、STL std::maxでは動作しません:here見られるようにstd :: maxへの関数ポインタを格納する自動変数

#include <algorithm> 

template <class T> 
T max2(const T& a, const T& b) { return std::max(a, b); } 

int main() { 
#if 1 
    auto f = max2<float>; 
#else 
    // error: unable to deduce ‘auto’ from ‘max<float>’ 
    auto f = std::max<float>; 
#endif 
    float max_val = f(1.0f, 2.0f); 
    return 0; 
} 
+1

問題は、[複数の 'のstd :: max'がある]ということである(http://en.cppreference.com/w/cpp/algorithm/max)とコンパイラはどちら君を知りません欲しいです。 –

+1

私は個人的に(非テンプレート)クラスを作成し、それにテンプレート関数呼び出し演算子(異なる署名を持つ複数の関数)を与え、そのクラスのオブジェクトを渡すテンプレート関数のスタイルを好みます。次に、テンプレートパラメータを指定する必要はありません。 'max 'の代わりに 'max'を渡すことができます。悪いことに、複数のフリー関数のオーバーロードがある場合に必要な不安定な静的キャストです。 [range-v3](https://github.com/ericniebler/range-v3)ライブラリは、すべての機能に対してこれを行います。 –

答えて

4

std::max<float>は、単一の、明確な関数ではありません。この時点で、それが過負荷セットだと二つの可能性が残っています:

constexpr const float& max(const float& a, const float& b); 
constexpr float max(std::initializer_list<float> ilist); 

次の2つの主要なオプションがあります。適切な型へ

  1. 出演:

    auto f = static_cast<const float&(*)(const float&, const float&)>(std::max); 
    
  2. ラップをそれはラムダで:

    auto f = [](float a, float b) { return std::max(a, b); }; 
    // Note there's no by-reference behaviour in this lambda. 
    

将来的には、より良い結果が期待できます。特に、リフレクションはユーティリティがauto f = lift(reflexpr(std::max));のようなものを使用する可能性があります。マクロを使ってこのようなことを今日エミュレートすることができます(マクロをラムダに展開することで最も簡単に行うことができます)。私はこれを行う少なくとも1つのLIFTマクロを見つけました。

2

std::maxには、複数のテンプレートオーバーロードがあります。どちらを使用するかを指定するにはstatic_castを使用できます。

static_castは、特定のタイプ

例えばする機能・ツー・ポインタ変換を行うことにより、関数オーバーロードを明確にするために使用されてもよい

auto f = static_cast<const float& (*)(const float&, const float&)>(std::max<float>); 
関連する問題