++ 14 . ++ 17 if constexpr, ; .
template<std::size_t I>
using index_t=std::integral_constant<std::size_t, I>;
template<std::size_t I>
constexpr index_t<I> index{};
constexpr inline index_t<0> dispatch_index() { return {}; }
template<class B0, class...Bs,
std::enable_if_t<B0::value, int> =0
>
constexpr index_t<0> dispatch_index( B0, Bs... ) { return {}; }
template<class B0, class...Bs,
std::enable_if_t<!B0::value, int> =0
>
constexpr auto dispatch_index( B0, Bs... ) {
return index< 1 + dispatch_index( decltype(Bs){}...) >;
}
template<class...Bs>
auto dispatch( Bs... ) {
using I = decltype(dispatch_index( decltype(Bs){}... ));
return [](auto&&...args)->decltype(auto){
return std::get<I::value>( std::make_tuple(decltype(args)(args)..., [](auto&&...){}) );
};
}
dispatch( some_test ) lambda, auto&&.... , , , some_test true-like-type, ( [](auto&&...){}, ), some_test false-like.
myArray.
namespace details {
template<template<class...>class Z, class=void, class...Ts>
struct can_apply:std::false_type{};
template<template<class...>class Z, class...Ts>
struct can_apply<Z, std::void_t<Z<Ts...>>, Ts...>:std::true_type{};
}
template<template<class...>class Z, class...Ts>
using can_apply = typename details::can_apply<Z, void, Ts...>::type;
template<class T>
using myArray_type = decltype( std::declval<T>().myArray );
template<class T>
using has_myArray = can_apply< myArray_type, T >;
has_myArray<T> , T .myArray.
dispatch( has_myArray<T>{} )(
[&](auto&& m) {
// do some processing with m.myArray
std::cout << sizeof(m.myArray) << std::endl;
// ...
}
)( m );
, m.myArray.
, , , , , , .
non-++ 11, MSVC 2015,
std::enable_if_t<B0::value, int> =0
std::enable_if_t<!B0::value, int> =0
class = std::enable_if_t<B0::value>
class = std::enable_if_t<!B0::value>, class=void
. , . MSVC.
++ 14, void_t enable_if_t, , enable_if.
, index ++ 11. index<blah> index_t<blah>{}.
auto&& lambdas ; , , . , auto lambdas, ++ 14 , , ++ 11.
, .