Generic Lambdas で has_xxx を実装する
has_xxx とは型 x にネストされた名前 name があるかどうか調べるメタ関数の総称です。名前空間またはクラスのスコープでクラステンプレート has_name を定義し、その上で has_name<x>::value などとして使います。
本の虫: C++11におけるモダンなhas_xxxの実装
しかし、一発で has(x, name) と書けると素敵です。C++14 で入るであろう Generic Lambdas (N3559) を使ってそれを書いてみました。
※ Concept Lite (N3580) の requires expression が来れば、素直にそれを使うべきです。
// 下準備... namespace has_xxx_detail { template <class F, class G> struct overload_result : F, G { overload_result(F f, G g) : F(f), G(g) {} using F::operator(); using G::operator(); }; template <class F, class G> overload_result<F, G> overload(F f, G g) { return {f, g}; } template <class T> struct identity { using type = T; }; struct bool_constant { constexpr operator std::true_type() { return {}; } constexpr operator std::false_type() { return {}; } }; } // namespace has_xxx_detail // x にネストされた型 name があるか調べる #define HAS_TYPE(x, name) \ ( \ false ? \ ::has_xxx_detail::overload( \ [](auto t, typename decltype(t)::type::name *) -> std::true_type { return {}; }, \ [](...) -> std::false_type { return {}; } \ )(::has_xxx_detail::identity<x>(), nullptr) : \ ::has_xxx_detail::bool_constant() \ ).value \ /**/ // x にネストされた非型 name があるか調べる #define HAS_VALUE(x, name) \ ( \ false ? \ ::has_xxx_detail::overload( \ [](auto t, decltype(&decltype(t)::type::name) *) -> std::true_type { return {}; }, \ [](...) -> std::false_type { return {}; } \ )(::has_xxx_detail::identity<x>(), nullptr) : \ ::has_xxx_detail::bool_constant() \ ).value \ /**/ struct yes { using type = int; static constexpr int value = 0; }; struct yes_for_value { void value() {} }; static_assert(HAS_TYPE(yes, type), ""); static_assert(HAS_VALUE(yes, value), ""); static_assert(!HAS_TYPE(yes_for_value, value), ""); static_assert(HAS_VALUE(yes_for_value, value), ""); static_assert(!HAS_VALUE(int, value), "");
こちらの Clang バイナリで動作を確認しました。ラムダ式を使っているため、unevaluated operand (decltype の中など) では使えないことに注意です。
なぜ Generic Lambdas でこれを実装できるというと、Generic Lambdas によって擬似的に式の中にテンプレートを書くことができるようになるからです。制約が強いので Generic Lambdas をそのままメタプログラミングに使うのは難しいですが、うまく使えば面白いことができそうです。