(この回答は @UncleBens と同じですが、引数を完全転送するため、もう少し一般的です。)
read
これは、入力として文字列を受け取り、目的の戻り値の型に従って解析する、haskell のような言語で非常に便利です。
(これはideone のサンプル コードです。)
まず、foo
推定する戻り値の型を持つ関数から始めます。
template<typename Ret>
Ret foo(const char *,int);
template<>
std::string foo<std::string>(const char *s,int) { return s; }
template<>
int foo<int >(const char *,int i) { return i; }
文字列を要求すると、最初の引数にある文字列を返します。int を要求すると、2 番目の引数が返されます。
auto_foo
次のように使用できる関数を定義できます。
int main() {
std::string s = auto_foo("hi",5); std::cout << s << std::endl;
int i = auto_foo("hi",5); std::cout << i << std::endl;
}
これを機能させるには、関数の引数を一時的に保存し、目的の戻り値の型に変換するよう求められたときに関数を実行するオブジェクトが必要です。
#include<tuple>
template<size_t num_args, typename ...T>
class Foo;
template<typename ...T>
class Foo<2,T...> : public std::tuple<T&&...>
{
public:
Foo(T&&... args) :
std::tuple<T&&...>(std::forward<T>(args)...)
{}
template< typename Return >
operator Return() { return foo<Return>(std::get<0>(*this), std::get<1>(*this)); }
};
template<typename ...T>
class Foo<3,T...> : std::tuple<T&&...>
{
public:
Foo(T&&... args) :
std::tuple<T&&...>(std::forward<T>(args)...)
{}
template< typename Return >
operator Return() { return foo<Return>(std::get<0>(*this), std::get<1>(*this), std::get<2>(*this)); }
};
template<typename ...T>
auto
auto_foo(T&&... args)
// -> Foo<T&&...> // old, incorrect, code
-> Foo< sizeof...(T), T&&...> // to count the arguments
{
return {std::forward<T>(args)...};
}
また、上記は 2 引数または 3 引数の関数で機能します。それを拡張する方法を理解することは難しくありません。
これは書くべきコードがたくさんあります!これを適用する関数ごとに、これを行うマクロを作成できます。ファイルの先頭に次のようなものがあります。
REGISTER_FUNCTION_FOR_DEDUCED_RETURN_TYPE(foo); // declares
// necessary structure and auto_???
そしてauto_foo
、プログラムで使用できます。