#ifndef COMPOSITE_STORAGE_TYPE_AT_HPP_INCLUDED #define COMPOSITE_STORAGE_TYPE_AT_HPP_INCLUDED #define TYPE_AT_N3761 0 //implementation uses code from: // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3761.html #define TYPE_AT_MPL (1+ TYPE_AT_N3761) //implementation uses code from: // http://www.boost.org/doc/libs/1_56_0/libs/mpl/doc/refmanual/at-c.html #define TYPE_AT_ANNOT (1+ TYPE_AT_MPL) //implementation uses code from page 9, item 3, of: // http://atpp.irrequietus.eu/atpp-c79f4b7.pdf //NOTE: as of 2014-09-10, no known compiler implements //the syntax described in this reference. #define TYPE_AT_PIGEON_HOLE (1+ TYPE_AT_ANNOT) //implementation uses code based on that of: // http://cpptruths.blogspot.com/2014/05/the-pigeonhole-principle-in-c.html //=============================================== #ifndef TYPE_AT_IMPL #define TYPE_AT_IMPL TYPE_AT_N3761 #endif #if TYPE_AT_MPL == TYPE_AT_IMPL #include #include #elif TYPE_AT_PIGEON_HOLE == TYPE_AT_IMPL #include //for std::declval #endif #include //for std::size_t namespace boost { namespace composite_storage { #if TYPE_AT_ANNOT == TYPE_AT_IMPL #else template struct type_at ; #endif #if TYPE_AT_N3761 == TYPE_AT_IMPL template struct type_at { using type = typename type_at::type; }; template struct type_at<0, S, T...> { using type = S; }; #elif TYPE_AT_MPL == TYPE_AT_IMPL template struct type_at { using type = typename boost::mpl::at_c < boost::mpl::vector , N >::type ; }; #elif TYPE_AT_ANNOT == TYPE_AT_IMPL template //specialized class template. If N not valid //index, this specialization won't be chosen. struct type_at < N , T... > { using type = T{N} ; }; #elif TYPE_AT_PIGEON_HOLE == TYPE_AT_IMPL namespace detail { struct any { template any(T&& t) /** * @brief * Provide a conversion constructor * for any type. */ { } }; template < typename T //the desired type. , typename U //An element in pack expansion > struct first /**@brief * Used to produce N repetitions of T * where N is sizeof...(Us) * and Us is declared as typename... Us * and U is one of the elements in Us. **@usage * typename first::type... */ { typedef T type; }; template < typename ...Ts //sizeof...(Ts)+1 is the index of the argument desired //in the static select method below. > struct select_impl { template static U&& select ( typename first::type... //Produces sizeof...(Ts) any formal arguments. //Since each any can be constructed from //T&& for any T, the 1st sizeof...(Ts) //actual arguments to this function can //converted to an any. //This leaves the next , unconverted, actual arg //in argument list as the argument desired. , U&& u //the desired argument [the (sizeof...(Ts)+1)-th argument]. , Vs&&... ) { return static_cast(u); } }; template < std::size_t... Idx , typename... Ts > static auto select ( const std::index_sequence& , Ts&&... ts ) /** * @brief * Return (N+1)-th ts, where N=sizeof...(Idx). */ { return select_impl < decltype(Idx)... //converts std::size_t args to types(all of type std::size_t) //because called function uses detail::first metafunction //which requires type args. >::select ( static_cast(ts)... //forward the actual arguments. ); } }//exit detail namespace template auto value_at(T &&...t) /** * @brief * return (N+1)-th t. */ { return detail::select(std::make_index_sequence(), static_cast(t)...); } template struct type_at { using type = decltype ( value_at ( std::declval() , std::declval()... ) ) ; }; #endif }//composite_storage namespace }//boost namespace #endif