#include <boost/hana/bool.hpp>
#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
#include <boost/hana/detail/operators/adl.hpp>
#include <boost/hana/detail/operators/comparable.hpp>
#include <boost/hana/fwd/concept/metafunction.hpp>
//////////////////////////////////////////////////////////////////////////
// template_
//////////////////////////////////////////////////////////////////////////
+ // Note: We have to use the very complicated trick below instead of just
+ // mentionning `F<T...>` in a SFINAE-able context because of CWG 1430
+ // (http://www.open-std.org/Jtc1/sc22/wg21/docs/cwg_active.html#1430).
+ namespace template_detail {
+ template <typename ...T> struct args;
+ template <typename ...> using always_void = void;
+
+ template <template <typename ...> class F, typename Args, typename = void>
+ struct specialization_is_valid
+ : std::false_type
+ { };
+
+ template <template <typename ...> class F, typename ...T>
+ struct specialization_is_valid<F, args<T...>, always_void<F<T...>>>
+ : std::true_type
+ { };
+ } // end namespace detail
+
template <template <typename ...> class F>
struct template_t {
template <typename ...T>
using type = F<T...>;
};
- template <typename ...T>
+ template <typename ...T, typename = std::enable_if_t<
+ template_detail::specialization_is_valid<F, template_detail::args<typename T::type...>>::value
+ >>
constexpr auto operator()(T const& ...) const
{ return hana::type<F<typename T::type...>>{}; }
};
operator()(T const& ...) const { return {}; }
};
+ //////////////////////////////////////////////////////////////////////////
+ // metafunction_class
+ //////////////////////////////////////////////////////////////////////////
+ namespace detail {
+ template <typename F, typename ...T>
+ struct always_first { using type = F; };
+ }
+ template <typename F>
+ struct metafunction_class_t {
+ template <typename ...T>
+ using apply = typename detail::always_first<F, T...>::type::template apply<T...>;
+
+ template <typename ...T>
+ constexpr hana::type<typename detail::always_first<F, T...>::type::template apply<typename T::type...>::type>
+ operator()(T const& ...) const { return {}; }
+ };
+
//////////////////////////////////////////////////////////////////////////
// Metafunction
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
template <typename F>
struct integral_t {
- template <typename ...T>
- constexpr auto operator()(T const& ...) const {
- using Result = typename F::template apply<typename T::type...>::type;
+ template <typename ...T, typename Result =
+ typename detail::always_first<F, T...>::type::template apply<typename T::type...>::type
+ >
+ constexpr Result operator()(T const& ...) const {
return Result{};
}
};