std::result_of<T>
は、タイプにかかわらず、T
が必要です。
template <class Fn, class... ArgTypes> struct result_of<Fn(ArgTypes...)>;
ように:T
はresult_of
のこの部分的な特殊化が使用されるように関数型である必要があり
decltype(INVOKE(declval<Fn>(), declval<ArgTypes>()...))
がよく形成されている(C++ 11 20.9.7.6) 。 (INVOKEは20.8.2で定義されています)
std::result_of<f(int)>
が機能しないのは、f
がタイプではないからです。これは、関数型のインスタンスです。タイプした場合
decltype(f(32)) x;
:
decltype(f(int{})) x;
か、ハードコーディングint
を好む場合:int
に適用f
の戻り値の型であることをx
を宣言するには、単にこれを書きますf
が望ましい場合は、次を使用します。
提供されるコード
F
(すなわち、低くない場合
f
)0
using FuncPtr = decltype(f);
しかしタイプなどF(int)
ある引数としてint
を受け入れるF
を返す関数を表すタイプを定義します。明らかにこれはFのものではありません! F
の型は、インスタンスが関数呼び出し演算子を使用できる構造体です。 F
には、int
などを取る明示的または暗黙的なコンストラクタもありません。これはどのように機能しますか?短い答え:テンプレート "魔法"。
本質的に、std::result_of
の定義では、タイプがF(int)
で、戻り値の型を引数の型から切り離して、INVOKE()がどのような場合に動作するかを判断できるようにします。 INVOKEの場合は、次のとおり
- Fは、唯一の引数がある場合、Fは、クラスTのデータメンバへのポインタであるか、または、
いくつかのクラスT
- ためのメンバ関数へのポインタでありますFの
- インスタンスは、すなわち関数として使用することができ、通常の関数呼び出しまたは(例えば、あなたの例のように)ファンクターのいくつかのタイプにすることができ
declval<F>()(declval<int>())
。
これが確定されると、result_of
は有効な式の戻り値の型を決定できます。これはresult_of
のtype
メンバーによって返されたものです。
これについての美しいことは、result_of
のユーザーは、これが実際にどのように動作するかについて何も知る必要がないということです。理解できる唯一のことは、result_of
が機能TYPEを必要とすることです。コード内に型名以外の名前(例:f
)を使用している場合は、decltype
を使用して、そのタイプの式を取得する必要があります。
最後に、f
が型と見なされない理由の一部は、テンプレートパラメータも定数値を許可し、f
が定数関数ポインタ値であるためです。これは、簡単に(f
の質問の定義を使用して)証明される:
template <double Op(int)>
double invoke_op(int i)
{
return Op(i);
}
以降:
std::cout << invoke_op<f>(10) << std::endl;
ので、適切にいくつかとf
を呼び出す式の戻り値の型を取得するためにint
1つは書くでしょう:
decltype(f(int{}))
(注:f
が呼び出されることはありません:コンパイラは、単純にその結果を決定するためにdecltype
内の式を使用していますつまり、この場合には、その戻り値。)
ソリューションは、この 'のstd :: result_of :: xを入力します。より深い理解が必要な場合は、この質問をチェックしてください。http://stackoverflow.com/q/2763824/893693 –
inf