1

MS Visual C++ 2012 バージョン 11.0.51106.01 Update 1 を使用する場合:

int x()
{
   return 3;
}

template <typename Fun>
typename std::enable_if<std::is_same<Fun, int()>::value, int>::type 
MySh(Fun& f)
{ 
   return f();
}

template <typename Fun>
typename std::enable_if<std::is_same<Fun, int()>::value, int>::type 
MySh1(Fun&& f)
{ 
   return f();
}

template <typename Fun>
int MySh2(Fun&& f)
{ 
   return f();
}

呼び出しコード:

   int res = MySh(x); // compiles and returns 3
   res = MySh1(x); // doesn't compile with error: error C2893: Failed to specialize function template 'std::enable_if<std::is_same<Fun,int(void)>::value,int>::type MySh1(Fun &&)
   res = MySh2(x); // compiles and returns 3

他のコンパイラは (まだ) 試していませんが、Visual C++ 2012 で動作するようにするか、コンパイラのバグを Microsoft に報告することを目的としています。

些細なことを見落としてばかげた間違いを犯していないことを確認したい. もちろん、サンプルは単なる抜粋であり、実際の使用例はより複雑で、以下に関連しています

編集: 次のような他の考慮事項にも混乱しました:

   std::is_same<decltype(x), int()>::value; // true
   std::is_same<decltype(x), int(&)()>::value; //false

と:

template <typename Fun>
typename std::enable_if<std::is_same<Fun, int(&)()>::value, int>::type 
MySh1(Fun&& f)
{ 
   std::cout << typeid(f).name() << std::endl;   // prints int __cdecl(void)
   return f();
}

明らかに、パラメーターの型と引数の型の違いに注意を払っていませんでした (f や x とは対照的に楽しい)。

4

2 に答える 2

2

答えはエラーです。宣言を次のように置き換えてください

template <typename Fun>
typename std::enable_if<std::is_same<Fun, int(&)()>::value, int>::type 
    MySh1(Fun&& f)
{ 
    return f();
}

これは、テンプレートを使用した場合の標準の特別な処理が原因で発生します<typename T> void foo(T&&);

いくつかの引数をfooに渡すと、次のようになります(例としてintの場合)。

  • パスlvalue int- Tですint&
  • パスlvalue const int-Tですconst int&
  • パスrvalue int-Tですint
  • パスrvalue const int-Tですconst int

スコットマイヤーズの良い記事はそれにもっと光を当てるかもしれません。

于 2013-02-24T05:33:54.550 に答える
2

Funそのコンテキストでの Aは、aFun&または aFun const&または aですFun&&-- は&&Fun上記の 3 つの参照のいずれかにバインドします (そしておそらくFun const&&? よくわかりません)。 &&型推論コンテキストにおける魔法の参照を意味します。

int()参照または const 参照または同じものへの右辺値参照の代わりにそれを比較しました。

参照型がstd::decay何に接続されているか気にしない場合は、を使用することをお勧めします。cvFun

のように

template <typename Fun>
typename std::enable_if<std::is_same<typename std::decay<Fun>::type, int(*)()>::value, int>::type 

さらに良いオプションはis_convertible

template <typename Fun>
typename std::enable_if<std::is_convertible<Fun, int(*)()>::value, int>::type 

これにより、[]()->intラムダが使用可能なものとして修飾されFunます。しかし、なぜそこで止まるのですか?

template <typename Fun>
typename std::enable_if<std::is_convertible<decltype(std::declval<Fun>()()), int>::value>::type 

Funのインスタンスが適用され、 に変換できる型を返すようなFun任意operator()の型を受け入れますint

次のいずれかを使用して、さらに先に進むこともできます。

template <typename Fun>
auto MySh_Alpha(Fun&& f)->decltype( f() )
{ 
  return f();
}

template <typename Fun>
decltype( std::declval<Fun>()() ) MySh_Alpha2(Fun&& f)
{ 
  return f();
}

これらは同等であり、渡されたMySh_Alphaものと同じ型を返すと言います。f

于 2013-02-24T06:21:35.150 に答える