メタプログラミングをするときにたまに関数の引数の型がを知りたいときがあるのでメモ。
std::tupleとstd::tuple_elementを使って実装します。
#include <type_traits>
#include <tuple>
template <std::size_t N, class...Args>
struct arg_type_impl
{
using type = typename std::tuple_element<N, std::tuple<Args...>>::type;
};
// 可変個引数テンプレート
template <std::size_t N, class... Args>
struct arg_type
{
using type = typename arg_type_impl<N, Args...>::type;
};
// 関数
template <std::size_t N, typename R, typename ... Args>
struct arg_type<N, R(*)(Args...)>
{
using type = typename arg_type_impl<N, Args...>::type;
};
// メンバー関数
template <std::size_t N, typename C, typename R, typename ... Args>
struct arg_type<N, R(C::*)(Args...)>
{
using type = typename arg_type_impl<N, Args...>::type;
};
// メンバー関数(const)
template <std::size_t N, typename C, typename R, typename ... Args>
struct arg_type<N, R(C::*)(Args...) const>
{
using type = typename arg_type_impl<N, Args...>::type;
};
// == テスト用の関数定義 ==
// 関数
static void hoge(int,double,int*);
// メンバー関数
struct X {
void hoge(int,double,int*);
void hoge_const(int,double,int*) const;
};
// == Test ==
// 可変個引数テンプレート
static_assert(std::is_same<int, arg_type<0, int,double,int*>::type>::value, "");
static_assert(std::is_same<double, arg_type<1, int,double,int*>::type>::value, "");
static_assert(std::is_same<int*, arg_type<2, int,double,int*>::type>::value, "");
// 関数
static_assert(std::is_same<int, arg_type<0, decltype(&hoge)>::type>::value, "");
static_assert(std::is_same<double, arg_type<1, decltype(&hoge)>::type>::value, "");
static_assert(std::is_same<int*, arg_type<2, decltype(&hoge)>::type>::value, "");
// メンバー関数
static_assert(std::is_same<int, arg_type<0, decltype(&X::hoge)>::type>::value, "");
static_assert(std::is_same<double, arg_type<1, decltype(&X::hoge)>::type>::value, "");
static_assert(std::is_same<int*, arg_type<2, decltype(&X::hoge)>::type>::value, "");
// メンバー関数(const)
static_assert(std::is_same<int, arg_type<0, decltype(&X::hoge_const)>::type>::value, "");
static_assert(std::is_same<double, arg_type<1, decltype(&X::hoge_const)>::type>::value, "");
static_assert(std::is_same<int*, arg_type<2, decltype(&X::hoge_const)>::type>::value, "");