次のような非常に単純だが長い関数を与えられた場合:
int foo(int a, int b, int c, int d) {
return 1;
}
// using ReturnTypeOfFoo = ???
コンパイル時に関数の戻り値の型(ReturnTypeOfFoo
、この例ではint
)を決定する最も簡単で簡潔な方法は何ですか関数のパラメーター型を繰り返さずに(名前による)のみ、関数に追加のオーバーロードがないことがわかっているため)
std::function
を活用して、関数の戻り型のtypedefを取得できます。 クラステンプレート引数の推論 に依存しているため、これにはC++ 17のサポートが必要ですが、呼び出し可能なすべての型で機能します。
using ReturnTypeOfFoo = decltype(std::function{foo})::result_type;
これをもう少し一般的にすることができます
template<typename Callable>
using return_type_of_t =
typename decltype(std::function{std::declval<Callable>()})::result_type;
その後、次のように使用できます
int foo(int a, int b, int c, int d) {
return 1;
}
auto bar = [](){ return 1; };
struct baz_
{
double operator()(){ return 0; }
} baz;
using ReturnTypeOfFoo = return_type_of_t<decltype(foo)>;
using ReturnTypeOfBar = return_type_of_t<decltype(bar)>;
using ReturnTypeOfBaz = return_type_of_t<decltype(baz)>;
最も単純で簡潔なものはおそらく次のとおりです。
template <typename R, typename... Args>
R return_type_of(R(*)(Args...));
using ReturnTypeOfFoo = decltype(return_type_of(foo));
これは、関数オブジェクトまたはメンバー関数へのポインターでは機能しないことに注意してください。オーバーロードされていない関数、テンプレート、またはnoexcept
。
ただし、必要に応じて、return_type_of
のオーバーロードを追加することで、これらのすべてのケースをサポートするように拡張できます。
私が最も簡単な方法であるかどうかはわかりません(C++ 17を使用できる場合はそうではありません:NathanOliverの答えを参照してください)が...次のように関数を宣言するのはどうですか:
template <typename R, typename ... Args>
R getRetType (R(*)(Args...));
decltype()
?を使用していますか?
using ReturnTypeOfFoo = decltype( getRetType(&foo) );
getRetType()
はdecltype()
のみと呼ばれるため、宣言されるだけで定義されないことに注意してください。したがって、返される型のみが関連します。