#ifndef SPROUT_BREED_DETAIL_DEDUCE_DOMAIN_HPP #define SPROUT_BREED_DETAIL_DEDUCE_DOMAIN_HPP #include #include #include #include #include // // SPROUT_BREED_ASSERT_VALID_DOMAIN // #ifndef SPROUT_BREED_ASSERT_VALID_DOMAIN # define SPROUT_BREED_ASSERT_VALID_DOMAIN(DOM) static_assert( \ !std::is_same::value, \ "!std::is_same::value" \ ) #endif namespace sprout { namespace breed { namespace detail { template struct domain_ : public domain_ { public: typedef Domain type; typedef domain_ base; public: using base::deduce_; static SPROUT_CONSTEXPR type deduce_(domain_ const*); }; template<> struct domain_ { public: typedef sprout::breed::detail::not_a_domain type; public: static type deduce_(void const*); }; template<> struct domain_ : public domain_ {}; template<> struct domain_ : public domain_ {}; sprout::breed::detail::sized_type<1>::type default_test( void const*, void const* ); sprout::breed::detail::sized_type<2>::type default_test( sprout::breed::detail::domain_ const*, void const* ); sprout::breed::detail::sized_type<2>::type default_test( sprout::breed::detail::domain_ const*, void const* ); sprout::breed::detail::sized_type<3>::type default_test( void const*, sprout::breed::detail::domain_ const* ); sprout::breed::detail::sized_type<3>::type default_test( void const*, sprout::breed::detail::domain_ const* ); sprout::breed::detail::sized_type<4>::type default_test( sprout::breed::detail::domain_ const*, sprout::breed::detail::domain_ const* ); sprout::breed::detail::sized_type<4>::type default_test( sprout::breed::detail::domain_ const*, sprout::breed::detail::domain_ const* ); sprout::breed::detail::sized_type<4>::type default_test( sprout::breed::detail::domain_ const*, sprout::breed::detail::domain_ const* ); sprout::breed::detail::sized_type<4>::type default_test( sprout::breed::detail::domain_ const*, sprout::breed::detail::domain_ const* ); template struct common_domain1 { public: typedef D0 type; }; template struct deduce_domain1 : public sprout::breed::domain_of {}; template< typename D0, typename D1, int DefaultCase = sizeof( sprout::breed::detail::default_test( static_cast const*>(0), static_cast const*>(0) ) ) > struct common_domain2 { public: typedef decltype(sprout::breed::detail::domain_::deduce_( static_cast const*>(0) )) type; }; template struct common_domain2 { public: typedef D1 type; }; template struct common_domain2 { public: typedef D0 type; }; template struct common_domain2 { public: typedef D0 type; }; template struct common_domain2 { public: typedef D0 type; }; template struct common_domain2 { public: typedef D1 type; }; template struct common_domain2 { public: typedef D1 type; }; template<> struct common_domain2 { public: typedef sprout::breed::default_domain type; }; template<> struct common_domain2 { public: typedef sprout::breed::default_domain type; }; template<> struct common_domain2 { public: typedef sprout::breed::default_domain type; }; template<> struct common_domain2 { public: typedef sprout::breed::basic_default_domain type; }; template struct deduce_domain2 : public common_domain2< typename sprout::breed::domain_of::type, typename sprout::breed::domain_of::type > {}; template struct common_domain { private: template struct common_impl { public: typedef typename common_impl< typename sprout::breed::detail::common_domain2::type, Tail... >::type type; }; template struct common_impl { public: typedef typename sprout::breed::detail::common_domain2::type type; }; public: template struct common : public common_impl {}; template struct common : public sprout::breed::detail::common_domain1 {}; public: typedef typename common::type type; SPROUT_BREED_ASSERT_VALID_DOMAIN(type); }; template struct deduce_domain_impl; template struct deduce_domain_impl, Args...> : public sprout::breed::detail::common_domain< typename sprout::breed::domain_of< typename sprout::tppack_at::type >::type... > {}; template struct deduce_domain : public sprout::breed::detail::deduce_domain_impl< typename sprout::index_range<0, sizeof...(Args)>::type, Args... > {}; } // namespace detail } // namespace breed } // namespace sprout #endif // #ifndef SPROUT_BREED_DETAIL_DEDUCE_DOMAIN_HPP