これはかなり複雑なC++ 14の機能です。 C++ 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)
auto&&...
をとるラムダを返します。 some_test
が真似型の場合は最初の引数を返し、some_test
がfalse-like型の場合は2番目の引数(または2番目の引数がない場合は[](auto&&...){}
)を返します。
次に、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
を持っている場合はtrueのようです。
我々は、これらが一緒に
dispatch(has_myArray<T>{})(
[&](auto&& m) {
// do some processing with m.myArray
std::cout << sizeof(m.myArray) << std::endl;
// ...
}
)(m);
、今途中でラムダはm.myArray
が有効である場合にのみ実行されるフック。
単なる存在以上のものをチェックする、より複雑なテストを書くことができますが、通常これで十分です。MSVC 2015のような非C++ 11コンパイラで
、
class = std::enable_if_t<B0::value>
と
class = std::enable_if_t<!B0::value>, class=void
と
std::enable_if_t<B0::value, int> =0
と
std::enable_if_t<!B0::value, int> =0
を置き換えますそれぞれ
である。はい、これらは醜いです。 MSVCコンパイラチームに相談してください。
コンパイラにC++ 14が不足している場合は、void_t
を書き、自分自身でenable_if_t
と書くか、enable_if
を使って醜い長いバージョンを使用する必要があります。
さらに、テンプレート変数index
は、C++ 11では不正です。 index<blah>
をindex_t<blah>{}
に交換してください。
auto&&
ラムダの欠如は上記を非常に痛ましいものにします。ラムダをアウトオブラインの関数オブジェクトに変換する必要があります。しかし、最初のC++ 14の機能の1つが実装されたオートラムダは、C++ 11を終了する前に実装されていました。
上記のコードは堅実に設計されていますが、誤植を含んでいる可能性があります。
C++ 17までは、1つの関数内でこれを行う方法がありません。 Constexpr if文が 'has_myArray'特性を持っていると、この動作が可能になります。 – 0x499602D2
@ 0x499602D2これはC++です – Yakk