1

次のように宣言された関数があります。その正確な動作はこれには関係ありません。

template<typename T>
std::pair<int, int>
partition3(T *pT, const int N, const T &Kq, const int w,
           std::function<int(const T&, const T&, int)> P);

コールサイトでは、次のことを試みます。

bool partition3_test()
{
  struct cmp
  {
    int operator()(int x, int y, int) const
    { return x-y; }
  };

  int V1[11] = { 3, 7, 1, 7, 7, 8, 10, 2, 16, 4, 3 },
      V2[11] = { 3, 6, 1, 6, 6, 8, 10, 2, 16, 4, 3 };

  std::function<int(const int&, const int&, int)> F = cmp();

  std::pair<int, int>
    p1  = partition3(V1, 11, 7, 0, cmp()),
    p2  = partition3(V2, 11, 7, 0, cmp());

  return false;
}

コンパイラー(MSVC 2010)の2つの呼び出しについてpartition3、最後のパラメーターのテンプレート引数を推測できなかったと文句を言います。に置き換えるcmp()F、コードがコンパイルされて正常に動作します。

2つの質問があります:

  1. なぜエラーが発生するのですか?[コンパイラのバグまたはいくつかの不可解なC++ルール?]
  2. 最初に明示的に構築せずに同じ効果を達成するにはどうすればよいFですか?

(現在、別のテンプレートパラメータを導入し、そのテンプレートタイプとしてpartition3宣言することで、問題を解決しました。)P

4

1 に答える 1

4

cmp()実際にはまったくありませんstd::function。コピーの初期化が機能するという事実は問題を混乱させるかもしれませんが、それはある種のラッパーオブジェクトを使用しなければならない変換コンストラクターを使用し、一時的なファンクターオブジェクトに対して機能することに驚いています(ああ、標準をチェックしていますどうやらファンクターのコピーを作成します)。

その上、関数の引数が一致しません(pass-by-valueとpass-by-const-referenceはソース互換ですが、runtime-call互換ではありません)。これもアダプターが必要です。

最善の解決策は、テンプレート関数をより汎用的にすることです。これにより、次の関数だけでなく、生の関数ポインターや任意のファンクターオブジェクトでも機能するようになりますstd::function

template<typename T, typename Functor>
std::pair<int, int> partition3(T *pT, const int N, const T &Kq, const int w,
                               const Functor& P);

何らかの理由で本当に使用したい場合std::function(たとえば、仮想ディスパッチが必要な場合)、使用できます。Nawazが書いたものとはまったく逆のエラーは、これ推論可能なコンテキストですが、複数のタイプが適合することです(std::functionタイプはパラメーターと正確に一致する必要がないため、アダプター/ラッパーの性質が重要になります。互換性がなければなりません。 std::function<int(const long&, const long&, int)>同様に一致します。)

代わりに、推論不可能なコンテキストを使用してください。そうすれば、コンパイラーは、の推論にファンクターを使用しようとさえしませんT

template<typename T, typename Functor>
std::pair<int, int> partition3(T *pT, const int N, const T &Kq, const int w,
                               std::function<std::identity<const T>::type&, std::identity<const T>::type&, int> P);
于 2012-04-15T13:34:37.367 に答える