Created
November 6, 2015 07:48
-
-
Save Nnwww/c64cb9316c6e0782b308 to your computer and use it in GitHub Desktop.
ジェネリックラムダ「以外」の(戻り値|引数)を推論して返すメタ関数
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <type_traits> | |
namespace m_utl | |
{ | |
template <typename... Types> | |
struct type_tuple {}; | |
// 関数の型を受け取り、戻り値を推定するメタ関数 | |
// ジェネリックラムダ以外であればこの中の何れかにオーバーロードされる | |
namespace result_of_function_impl | |
{ | |
// 関数 | |
template < typename Result, typename ... Args > | |
auto eval( Result( * )( Args ... ) ) -> Result; | |
// メンバ関数ポインタ(非const) | |
template < typename T, typename Result, typename ... Args > | |
auto eval( Result( T::* )( Args ... ) ) -> Result; | |
// メンバ関数ポインタ(const) | |
template < typename T, typename Result, typename ... Args > | |
auto eval( Result( T::* )( Args ... ) const ) -> Result; | |
// 関数オブジェクト(非ジェネリックラムダ) | |
template < typename T, typename FuncType = decltype( &T::operator() ) > | |
auto eval( T* ) -> decltype( eval( std::declval<FuncType>() ) ); | |
// ジェネリックラムダはテンプレート引数の指定が不可であり、型が定まらないため、実装は見送る | |
} | |
// 関数の型を受け取り、引数を型タプルに包んで返すメタ関数 | |
// ジェネリックラムダ以外であればこの中の何れかにオーバーロードされる | |
namespace args_of_function_impl | |
{ | |
// 関数 | |
template < typename Result, typename ... Args > | |
auto eval( Result( * )( Args ... ) ) -> type_tuple<Args...>; | |
// メンバ関数ポインタ(非const) | |
template < typename T, typename Result, typename ... Args > | |
auto eval( Result( T::* )( Args ... ) ) -> type_tuple<Args...>; | |
// メンバ関数ポインタ(const) | |
template < typename T, typename Result, typename ... Args > | |
auto eval( Result( T::* )( Args ... ) const ) -> type_tuple<Args...>; | |
// 関数オブジェクト(非ジェネリックラムダ) | |
template < typename T, typename FuncType = decltype( &T::operator() ) > | |
auto eval( T* ) -> decltype( eval( std::declval<FuncType>() ) ); | |
// ジェネリックラムダはテンプレート引数の指定が不可であり、型が定まらないため、実装は見送る | |
} | |
// インターフェースとしてこれつかってね | |
template < class T > | |
using res_of_fn = decltype( result_of_function_impl::eval( std::declval<std::remove_pointer_t<T>*>() ) ); | |
template < class T > | |
using args_of_fn = decltype( args_of_function_impl::eval( std::declval<std::remove_pointer_t<T>*>() ) ); | |
} // m_utl |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment