C++11でタプルを関数の引数へ渡す
C++11の環境ではinteger sequenceが標準搭載されていないので、そういった場合への対処法としてメモ。以下のコードはclang 4.0.0の-std=c++11モードで確認している。
まず単純に再起して、パラメータパックがたまりきった所で呼び出す方法。
inline void foo(){} template<class T,class... Args> void foo(T&& head,Args&&... tail) { std::cout<<head<<std::endl; return foo(std::forward<Args>(tail)...); } template<class... Args> auto expr(Args&&... args)->void { return foo(std::forward<Args>(args)...); } struct call_impl{ struct call_function{ template<class _Tp,std::size_t l,class Tuple,class... Args> static auto invoke(const std::integral_constant<_Tp,l>&,Tuple&&,Args&&... args)->void { return expr(std::forward<Args>(args)...); } }; struct unpack{ template<class _Tp,std::size_t l,class Tuple,class... Args> static auto invoke(const std::integral_constant<_Tp,l>&,Tuple&& t,Args&&... args)->void { return apply(std::integral_constant<_Tp,l+1>(),std::forward<Tuple>(t),std::forward<Args>(args)...,std::get<l>(t)); } }; template<class _Tp,std::size_t l,class Tuple,class... Args> static auto apply(const std::integral_constant<_Tp,l>& intconstant,Tuple&& t,Args&&... arg)->void { return std::conditional< sizeof...(arg)==std::tuple_size<typename std::remove_reference<Tuple>::type>::value, call_function, unpack >::type::invoke(intconstant,std::forward<Tuple>(t),std::forward<Args>(arg)...); } }; template<class Tuple> auto invoke(Tuple&& t)->void { call_impl::apply(std::integral_constant<std::size_t,0>(),std::forward<Tuple>(t)); } int main() { std::tuple<int,char,bool,float> t{42,'a',true,4.2f}; invoke(t); }
次にinteger sequenceを自作する方法。
template<class T,T... Ts> struct integer_sequence{ typedef T value_type; static constexpr std::size_t size()noexcept{return sizeof...(Ts);} }; template<std::size_t... V> using index_sequence=integer_sequence<std::size_t,V...>; template<std::size_t,class> struct make_index_sequence_impl; template<std::size_t n,std::size_t... l> struct make_index_sequence_impl<n,index_sequence<l...>>{ typedef typename make_index_sequence_impl<n-1,index_sequence<n-1,l...>>::type type; }; template<std::size_t... l> struct make_index_sequence_impl<0,index_sequence<l...>>{ typedef index_sequence<l...> type; }; template<std::size_t n,class T=index_sequence<>> using make_index_sequence=typename make_index_sequence_impl<n,T>::type; void hoge(){} template<class Head,class... Tail> auto hoge(Head&& head,Tail&&... tail)->void { std::cout<<std::forward<Head>(head)<<std::endl; hoge(std::forward<Tail>(tail)...); } template<class Tuple,std::size_t... l> auto invoke_impl(Tuple&& t,index_sequence<l...>)->void { hoge(std::get<l>(t)...); } template<class Tuple> void invoke(Tuple&& t) { invoke_impl(std::forward<Tuple>(t),make_index_sequence<std::tuple_size<Tuple>::value>()); } int main() { invoke(std::tuple<int,char,bool,float>{42,'a',true,42.0f}); }