Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:53:55

0001 // Copyright (C) 2016-2018 T. Zachary Laine
0002 //
0003 // Distributed under the Boost Software License, Version 1.0. (See
0004 // accompanying file LICENSE_1_0.txt or copy at
0005 // http://www.boost.org/LICENSE_1_0.txt)
0006 #ifndef BOOST_YAP_DETAIL_EXPRESSION_HPP_INCLUDED
0007 #define BOOST_YAP_DETAIL_EXPRESSION_HPP_INCLUDED
0008 
0009 #include <boost/yap/algorithm_fwd.hpp>
0010 
0011 #include <boost/hana/size.hpp>
0012 #include <boost/hana/tuple.hpp>
0013 
0014 #include <memory>
0015 #include <type_traits>
0016 
0017 
0018 namespace boost { namespace yap { namespace detail {
0019 
0020     // static_const
0021 
0022     template<typename T>
0023     struct static_const
0024     {
0025         static constexpr T value{};
0026     };
0027 
0028     template<typename T>
0029     constexpr T static_const<T>::value;
0030 
0031 
0032     // partial_decay
0033 
0034     template<typename T>
0035     struct partial_decay
0036     {
0037         using type = T;
0038     };
0039 
0040     template<typename T>
0041     struct partial_decay<T[]>
0042     {
0043         using type = T *;
0044     };
0045     template<typename T, std::size_t N>
0046     struct partial_decay<T[N]>
0047     {
0048         using type = T *;
0049     };
0050 
0051     template<typename T>
0052     struct partial_decay<T (&)[]>
0053     {
0054         using type = T *;
0055     };
0056     template<typename T, std::size_t N>
0057     struct partial_decay<T (&)[N]>
0058     {
0059         using type = T *;
0060     };
0061 
0062     template<typename R, typename... A>
0063     struct partial_decay<R(A...)>
0064     {
0065         using type = R (*)(A...);
0066     };
0067     template<typename R, typename... A>
0068     struct partial_decay<R(A..., ...)>
0069     {
0070         using type = R (*)(A..., ...);
0071     };
0072 
0073     template<typename R, typename... A>
0074     struct partial_decay<R (&)(A...)>
0075     {
0076         using type = R (*)(A...);
0077     };
0078     template<typename R, typename... A>
0079     struct partial_decay<R (&)(A..., ...)>
0080     {
0081         using type = R (*)(A..., ...);
0082     };
0083 
0084     template<typename R, typename... A>
0085     struct partial_decay<R (*&)(A...)>
0086     {
0087         using type = R (*)(A...);
0088     };
0089     template<typename R, typename... A>
0090     struct partial_decay<R (*&)(A..., ...)>
0091     {
0092         using type = R (*)(A..., ...);
0093     };
0094 
0095 
0096     // operand_value_type_phase_1
0097 
0098     template<
0099         typename T,
0100         typename U = typename detail::partial_decay<T>::type,
0101         bool AddRValueRef = std::is_same<T, U>::value && !std::is_const<U>::value>
0102     struct operand_value_type_phase_1;
0103 
0104     template<typename T, typename U>
0105     struct operand_value_type_phase_1<T, U, true>
0106     {
0107         using type = U &&;
0108     };
0109 
0110     template<typename T, typename U>
0111     struct operand_value_type_phase_1<T, U, false>
0112     {
0113         using type = U;
0114     };
0115 
0116 
0117     // expr_ref
0118 
0119     template<template<expr_kind, class> class ExprTemplate, typename T>
0120     struct expr_ref
0121     {
0122         using type = expression_ref<ExprTemplate, T>;
0123     };
0124 
0125     template<template<expr_kind, class> class ExprTemplate, typename Tuple>
0126     struct expr_ref<ExprTemplate, ExprTemplate<expr_kind::expr_ref, Tuple> &>
0127     {
0128         using type = ExprTemplate<expr_kind::expr_ref, Tuple>;
0129     };
0130 
0131     template<template<expr_kind, class> class ExprTemplate, typename Tuple>
0132     struct expr_ref<
0133         ExprTemplate,
0134         ExprTemplate<expr_kind::expr_ref, Tuple> const &>
0135     {
0136         using type = ExprTemplate<expr_kind::expr_ref, Tuple>;
0137     };
0138 
0139     template<template<expr_kind, class> class ExprTemplate, typename T>
0140     using expr_ref_t = typename expr_ref<ExprTemplate, T>::type;
0141 
0142     template<template<expr_kind, class> class ExprTemplate, typename T>
0143     struct expr_ref_tuple;
0144 
0145     template<template<expr_kind, class> class ExprTemplate, typename Tuple>
0146     struct expr_ref_tuple<
0147         ExprTemplate,
0148         ExprTemplate<expr_kind::expr_ref, Tuple>>
0149     {
0150         using type = Tuple;
0151     };
0152 
0153     template<template<expr_kind, class> class ExprTemplate, typename T>
0154     using expr_ref_tuple_t = typename expr_ref_tuple<ExprTemplate, T>::type;
0155 
0156 
0157     // operand_type
0158 
0159     template<
0160         template<expr_kind, class> class ExprTemplate,
0161         typename T,
0162         typename U = typename operand_value_type_phase_1<T>::type,
0163         bool RemoveRefs = std::is_rvalue_reference<U>::value,
0164         bool IsExpr = is_expr<T>::value,
0165         bool IsLRef = std::is_lvalue_reference<T>::value>
0166     struct operand_type;
0167 
0168     template<
0169         template<expr_kind, class> class ExprTemplate,
0170         typename T,
0171         typename U,
0172         bool RemoveRefs>
0173     struct operand_type<ExprTemplate, T, U, RemoveRefs, true, false>
0174     {
0175         using type = remove_cv_ref_t<T>;
0176     };
0177 
0178     template<
0179         template<expr_kind, class> class ExprTemplate,
0180         typename T,
0181         typename U,
0182         bool RemoveRefs>
0183     struct operand_type<ExprTemplate, T, U, RemoveRefs, true, true>
0184     {
0185         using type = expr_ref_t<ExprTemplate, T>;
0186     };
0187 
0188     template<
0189         template<expr_kind, class> class ExprTemplate,
0190         typename T,
0191         typename U,
0192         bool RemoveRefs,
0193         bool IsLRef>
0194     struct operand_type<ExprTemplate, T, U, RemoveRefs, true, IsLRef>
0195     {
0196         using type = remove_cv_ref_t<T>;
0197     };
0198 
0199     template<
0200         template<expr_kind, class> class ExprTemplate,
0201         typename T,
0202         typename U,
0203         bool IsLRef>
0204     struct operand_type<ExprTemplate, T, U, true, false, IsLRef>
0205     {
0206         using type = terminal<ExprTemplate, std::remove_reference_t<U>>;
0207     };
0208 
0209     template<
0210         template<expr_kind, class> class ExprTemplate,
0211         typename T,
0212         typename U,
0213         bool IsLRef>
0214     struct operand_type<ExprTemplate, T, U, false, false, IsLRef>
0215     {
0216         using type = terminal<ExprTemplate, U>;
0217     };
0218 
0219     template<template<expr_kind, class> class ExprTemplate, typename T>
0220     using operand_type_t = typename operand_type<ExprTemplate, T>::type;
0221 
0222 
0223     // make_operand
0224 
0225     template<typename T>
0226     struct make_operand
0227     {
0228         template<typename U>
0229         constexpr auto operator()(U && u)
0230         {
0231             return T{static_cast<U &&>(u)};
0232         }
0233     };
0234 
0235     template<template<expr_kind, class> class ExprTemplate, typename Tuple>
0236     struct make_operand<ExprTemplate<expr_kind::expr_ref, Tuple>>
0237     {
0238         constexpr auto operator()(ExprTemplate<expr_kind::expr_ref, Tuple> expr)
0239         {
0240             return expr;
0241         }
0242 
0243         template<typename U>
0244         constexpr auto operator()(U && u)
0245         {
0246             return ExprTemplate<expr_kind::expr_ref, Tuple>{
0247                 Tuple{std::addressof(u)}};
0248         }
0249     };
0250 
0251 
0252     // free_binary_op_result
0253 
0254     template<
0255         template<expr_kind, class> class ExprTemplate,
0256         expr_kind OpKind,
0257         typename T,
0258         typename U,
0259         bool TNonExprUExpr = !is_expr<T>::value && is_expr<U>::value,
0260         bool ULvalueRef = std::is_lvalue_reference<U>::value>
0261     struct free_binary_op_result;
0262 
0263     template<
0264         template<expr_kind, class> class ExprTemplate,
0265         expr_kind OpKind,
0266         typename T,
0267         typename U>
0268     struct free_binary_op_result<ExprTemplate, OpKind, T, U, true, true>
0269     {
0270         using lhs_type = operand_type_t<ExprTemplate, T>;
0271         using rhs_type = expr_ref_t<ExprTemplate, U>;
0272         using rhs_tuple_type = expr_ref_tuple_t<ExprTemplate, rhs_type>;
0273         using type = ExprTemplate<OpKind, hana::tuple<lhs_type, rhs_type>>;
0274     };
0275 
0276     template<
0277         template<expr_kind, class> class ExprTemplate,
0278         expr_kind OpKind,
0279         typename T,
0280         typename U>
0281     struct free_binary_op_result<ExprTemplate, OpKind, T, U, true, false>
0282     {
0283         using lhs_type = operand_type_t<ExprTemplate, T>;
0284         using rhs_type = remove_cv_ref_t<U>;
0285         using type = ExprTemplate<OpKind, hana::tuple<lhs_type, rhs_type>>;
0286     };
0287 
0288     template<
0289         template<expr_kind, class> class ExprTemplate,
0290         expr_kind OpKind,
0291         typename T,
0292         typename U>
0293     using free_binary_op_result_t =
0294         typename free_binary_op_result<ExprTemplate, OpKind, T, U>::type;
0295 
0296 
0297     // ternary_op_result
0298 
0299     template<
0300         template<expr_kind, class> class ExprTemplate,
0301         typename T,
0302         typename U,
0303         typename V,
0304         bool Valid =
0305             is_expr<T>::value || is_expr<U>::value || is_expr<V>::value>
0306     struct ternary_op_result;
0307 
0308     template<
0309         template<expr_kind, class> class ExprTemplate,
0310         typename T,
0311         typename U,
0312         typename V>
0313     struct ternary_op_result<ExprTemplate, T, U, V, true>
0314     {
0315         using cond_type = operand_type_t<ExprTemplate, T>;
0316         using then_type = operand_type_t<ExprTemplate, U>;
0317         using else_type = operand_type_t<ExprTemplate, V>;
0318         using type = ExprTemplate<
0319             expr_kind::if_else,
0320             hana::tuple<cond_type, then_type, else_type>>;
0321     };
0322 
0323     template<
0324         template<expr_kind, class> class ExprTemplate,
0325         typename T,
0326         typename U,
0327         typename V>
0328     using ternary_op_result_t =
0329         typename ternary_op_result<ExprTemplate, T, U, V>::type;
0330 
0331 
0332     // udt_any_ternary_op_result
0333 
0334     template<
0335         template<expr_kind, class> class ExprTemplate,
0336         typename T,
0337         typename U,
0338         typename V,
0339         template<class> class UdtTrait,
0340         bool Valid = !is_expr<T>::value && !is_expr<U>::value &&
0341                      !is_expr<V>::value &&
0342                      (UdtTrait<remove_cv_ref_t<T>>::value ||
0343                       UdtTrait<remove_cv_ref_t<U>>::value ||
0344                       UdtTrait<remove_cv_ref_t<V>>::value)>
0345     struct udt_any_ternary_op_result;
0346 
0347     template<
0348         template<expr_kind, class> class ExprTemplate,
0349         typename T,
0350         typename U,
0351         typename V,
0352         template<class> class UdtTrait>
0353     struct udt_any_ternary_op_result<ExprTemplate, T, U, V, UdtTrait, true>
0354     {
0355         using cond_type = operand_type_t<ExprTemplate, T>;
0356         using then_type = operand_type_t<ExprTemplate, U>;
0357         using else_type = operand_type_t<ExprTemplate, V>;
0358         using type = ExprTemplate<
0359             expr_kind::if_else,
0360             hana::tuple<cond_type, then_type, else_type>>;
0361     };
0362 
0363     template<
0364         template<expr_kind, class> class ExprTemplate,
0365         typename T,
0366         typename U,
0367         typename V,
0368         template<class> class UdtTrait>
0369     using udt_any_ternary_op_result_t =
0370         typename udt_any_ternary_op_result<ExprTemplate, T, U, V, UdtTrait>::
0371             type;
0372 
0373 
0374     // udt_unary_op_result
0375 
0376     template<
0377         template<expr_kind, class> class ExprTemplate,
0378         expr_kind OpKind,
0379         typename T,
0380         template<class> class UdtTrait,
0381         bool Valid = !is_expr<T>::value && UdtTrait<remove_cv_ref_t<T>>::value>
0382     struct udt_unary_op_result;
0383 
0384     template<
0385         template<expr_kind, class> class ExprTemplate,
0386         expr_kind OpKind,
0387         typename T,
0388         template<class> class UdtTrait>
0389     struct udt_unary_op_result<ExprTemplate, OpKind, T, UdtTrait, true>
0390     {
0391         using x_type = operand_type_t<ExprTemplate, T>;
0392         using type = ExprTemplate<OpKind, hana::tuple<x_type>>;
0393     };
0394 
0395     template<
0396         template<expr_kind, class> class ExprTemplate,
0397         expr_kind OpKind,
0398         typename T,
0399         template<class> class UdtTrait>
0400     using udt_unary_op_result_t =
0401         typename udt_unary_op_result<ExprTemplate, OpKind, T, UdtTrait>::type;
0402 
0403 
0404     // udt_udt_binary_op_result
0405 
0406     template<typename T, template<class> class UdtTrait>
0407     struct is_udt_arg
0408     {
0409         static bool const value =
0410             !is_expr<T>::value && UdtTrait<remove_cv_ref_t<T>>::value;
0411     };
0412 
0413     template<
0414         template<expr_kind, class> class ExprTemplate,
0415         expr_kind OpKind,
0416         typename T,
0417         typename U,
0418         template<class> class TUdtTrait,
0419         template<class> class UUdtTrait,
0420         bool Valid =
0421             is_udt_arg<T, TUdtTrait>::value && is_udt_arg<U, UUdtTrait>::value>
0422     struct udt_udt_binary_op_result;
0423 
0424     template<
0425         template<expr_kind, class> class ExprTemplate,
0426         expr_kind OpKind,
0427         typename T,
0428         typename U,
0429         template<class> class TUdtTrait,
0430         template<class> class UUdtTrait>
0431     struct udt_udt_binary_op_result<
0432         ExprTemplate,
0433         OpKind,
0434         T,
0435         U,
0436         TUdtTrait,
0437         UUdtTrait,
0438         true>
0439     {
0440         using lhs_type = operand_type_t<ExprTemplate, T>;
0441         using rhs_type = operand_type_t<ExprTemplate, U>;
0442         using type = ExprTemplate<OpKind, hana::tuple<lhs_type, rhs_type>>;
0443     };
0444 
0445     template<
0446         template<expr_kind, class> class ExprTemplate,
0447         expr_kind OpKind,
0448         typename T,
0449         typename U,
0450         template<class> class TUdtTrait,
0451         template<class> class UUdtTrait>
0452     using udt_udt_binary_op_result_t = typename udt_udt_binary_op_result<
0453         ExprTemplate,
0454         OpKind,
0455         T,
0456         U,
0457         TUdtTrait,
0458         UUdtTrait>::type;
0459 
0460 
0461     // udt_any_binary_op_result
0462 
0463     template<
0464         template<expr_kind, class> class ExprTemplate,
0465         expr_kind OpKind,
0466         typename T,
0467         typename U,
0468         template<class> class UdtTrait,
0469         bool Valid = !is_expr<T>::value && !is_expr<U>::value &&
0470                      (UdtTrait<remove_cv_ref_t<T>>::value ||
0471                       UdtTrait<remove_cv_ref_t<U>>::value)>
0472     struct udt_any_binary_op_result;
0473 
0474     template<
0475         template<expr_kind, class> class ExprTemplate,
0476         expr_kind OpKind,
0477         typename T,
0478         typename U,
0479         template<class> class UdtTrait>
0480     struct udt_any_binary_op_result<ExprTemplate, OpKind, T, U, UdtTrait, true>
0481     {
0482         using lhs_type = operand_type_t<ExprTemplate, T>;
0483         using rhs_type = operand_type_t<ExprTemplate, U>;
0484         using type = ExprTemplate<OpKind, hana::tuple<lhs_type, rhs_type>>;
0485     };
0486 
0487     template<
0488         template<expr_kind, class> class ExprTemplate,
0489         expr_kind OpKind,
0490         typename T,
0491         typename U,
0492         template<class> class UdtTrait>
0493     using udt_any_binary_op_result_t = typename udt_any_binary_op_result<
0494         ExprTemplate,
0495         OpKind,
0496         T,
0497         U,
0498         UdtTrait>::type;
0499 
0500 
0501     // not_copy_or_move
0502 
0503     template<typename LeftT, typename RightT>
0504     struct copy_or_move : std::false_type
0505     {
0506     };
0507 
0508     template<typename T>
0509     struct copy_or_move<T, T const &> : std::true_type
0510     {
0511     };
0512 
0513     template<typename T>
0514     struct copy_or_move<T, T &> : std::true_type
0515     {
0516     };
0517 
0518     template<typename T>
0519     struct copy_or_move<T, T &&> : std::true_type
0520     {
0521     };
0522 
0523 
0524     // expr_arity
0525 
0526     enum class expr_arity { invalid, one, two, three, n };
0527 
0528     template<expr_kind Kind>
0529     constexpr expr_arity arity_of()
0530     {
0531         switch (Kind) {
0532         case expr_kind::expr_ref:
0533 
0534         case expr_kind::terminal:
0535 
0536         // unary
0537         case expr_kind::unary_plus:  // +
0538         case expr_kind::negate:      // -
0539         case expr_kind::dereference: // *
0540         case expr_kind::complement:  // ~
0541         case expr_kind::address_of:  // &
0542         case expr_kind::logical_not: // !
0543         case expr_kind::pre_inc:     // ++
0544         case expr_kind::pre_dec:     // --
0545         case expr_kind::post_inc:    // ++(int)
0546         case expr_kind::post_dec:    // --(int)
0547             return expr_arity::one;
0548 
0549         // binary
0550         case expr_kind::shift_left:         // <<
0551         case expr_kind::shift_right:        // >>
0552         case expr_kind::multiplies:         // *
0553         case expr_kind::divides:            // /
0554         case expr_kind::modulus:            // %
0555         case expr_kind::plus:               // +
0556         case expr_kind::minus:              // -
0557         case expr_kind::less:               // <
0558         case expr_kind::greater:            // >
0559         case expr_kind::less_equal:         // <=
0560         case expr_kind::greater_equal:      // >=
0561         case expr_kind::equal_to:           // ==
0562         case expr_kind::not_equal_to:       // !=
0563         case expr_kind::logical_or:         // ||
0564         case expr_kind::logical_and:        // &&
0565         case expr_kind::bitwise_and:        // &
0566         case expr_kind::bitwise_or:         // |
0567         case expr_kind::bitwise_xor:        // ^
0568         case expr_kind::comma:              // :
0569         case expr_kind::mem_ptr:            // ->*
0570         case expr_kind::assign:             // =
0571         case expr_kind::shift_left_assign:  // <<=
0572         case expr_kind::shift_right_assign: // >>=
0573         case expr_kind::multiplies_assign:  // *=
0574         case expr_kind::divides_assign:     // /=
0575         case expr_kind::modulus_assign:     // %=
0576         case expr_kind::plus_assign:        // +=
0577         case expr_kind::minus_assign:       // -=
0578         case expr_kind::bitwise_and_assign: // &=
0579         case expr_kind::bitwise_or_assign:  // |=
0580         case expr_kind::bitwise_xor_assign: // ^=
0581         case expr_kind::subscript:          // []
0582             return expr_arity::two;
0583 
0584         // ternary
0585         case expr_kind::if_else: // (analogous to) ?:
0586             return expr_arity::three;
0587 
0588         // n-ary
0589         case expr_kind::call: // ()
0590             return expr_arity::n;
0591 
0592         default: return expr_arity::invalid;
0593         }
0594     }
0595 
0596 }}}
0597 
0598 #endif