Sprout/sprout/breed/domain.hpp

184 lines
4.6 KiB
C++
Raw Normal View History

#ifndef SPROUT_BREED_DOMAIN_HPP
#define SPROUT_BREED_DOMAIN_HPP
#include <functional>
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/breed/breed_fwd.hpp>
#include <sprout/breed/generate.hpp>
#include <sprout/breed/detail/as_expr.hpp>
#include <sprout/breed/detail/deduce_domain.hpp>
namespace sprout {
namespace breed {
namespace detail {
struct not_a_generator {};
struct not_a_grammar {};
struct not_a_domain {};
} // namespace detail
namespace domainns_ {
//
// domain
//
template<
typename Generator,
typename Grammar,
typename Super
>
struct domain
: public Generator
{
public:
typedef Generator breed_generator;
typedef Grammar breed_grammar;
typedef Super breed_super_domain;
typedef domain breed_base_domain;
typedef void breed_is_domain_;
public:
template<typename T, typename IsExpr = void, typename Callable = sprout::breed::callable>
struct as_expr
: public detail::as_expr<
T,
typename sprout::breed::detail::base_generator<Generator>::type,
sprout::breed::wants_basic_expr<Generator>::value
>
{
public:
SPROUT_BREED_CALLABLE()
};
template<typename T>
struct as_expr<T, typename T::breed_is_expr_, sprout::breed::callable> {
public:
SPROUT_BREED_CALLABLE()
public:
typedef typename std::remove_const<T>::type result_type;
public:
SPROUT_CONSTEXPR result_type operator()(T const& e) const {
return e;
}
};
template<typename T, typename IsExpr = void, typename Callable = sprout::breed::callable>
struct as_child
: public detail::as_child<
T,
typename sprout::breed::detail::base_generator<Generator>::type,
sprout::breed::wants_basic_expr<Generator>::value
>
{
public:
SPROUT_BREED_CALLABLE()
};
template<typename T>
struct as_child<T, typename T::breed_is_expr_, sprout::breed::callable> {
public:
SPROUT_BREED_CALLABLE()
public:
typedef T &result_type;
public:
SPROUT_CONSTEXPR result_type operator()(T const& e) const {
return e;
}
};
};
//
// default_domain
//
struct default_domain
: public sprout::breed::domain<>
{};
//
// basic_default_domain
//
struct basic_default_domain
: public sprout::breed::domain<sprout::breed::basic_default_generator>
{};
//
// deduce_domain
//
struct deduce_domain
: public sprout::breed::domain<
sprout::breed::detail::not_a_generator,
sprout::breed::detail::not_a_grammar,
sprout::breed::detail::not_a_domain
>
{};
//
// base_expr
//
template<typename Domain, typename Tag, typename Args, bool WantsBasicExpr>
struct base_expr {
public:
typedef sprout::breed::expr<Tag, Args, Args::arity> type;
};
template<typename Domain, typename Tag, typename Args>
struct base_expr<Domain, Tag, Args, true> {
public:
typedef sprout::breed::basic_expr<Tag, Args, Args::arity> type;
};
} // namespace domainns_
//
// is_domain
//
template<typename T, typename Void>
struct is_domain
: public std::false_type
{};
template<typename T>
struct is_domain<T, typename T::breed_is_domain_>
: public std::true_type
{};
//
// domain_of
//
template<typename T, typename Void>
struct domain_of {
public:
typedef sprout::breed::default_domain type;
};
template<typename T>
struct domain_of<T, typename T::breed_is_expr_> {
public:
typedef typename T::breed_domain type;
};
template<typename T>
struct domain_of<T&, void> {
public:
typedef typename sprout::breed::domain_of<T>::type type;
};
template<typename T>
struct domain_of<std::reference_wrapper<T>, void> {
public:
typedef typename sprout::breed::domain_of<T>::type type;
};
template<typename T>
struct domain_of<std::reference_wrapper<T> const, void> {
typedef typename sprout::breed::domain_of<T>::type type;
};
//
// is_sub_domain_of
//
template<typename SubDomain, typename SuperDomain>
struct is_sub_domain_of
: public is_sub_domain_of<typename SubDomain::breed_super_domain, SuperDomain>
{};
template<typename SuperDomain>
struct is_sub_domain_of<sprout::breed::no_super_domain, SuperDomain>
: public std::false_type
{};
template<typename SuperDomain>
struct is_sub_domain_of<SuperDomain, SuperDomain>
: public std::true_type
{};
} // namespace breed
} // namespace sprout
#endif // #ifndef SPROUT_BREED_DOMAIN_HPP