1 /* 2 Copyright (C) 2013 Tom Bachmann 3 4 This file is part of FLINT. 5 6 FLINT is free software: you can redistribute it and/or modify it under 7 the terms of the GNU Lesser General Public License (LGPL) as published 8 by the Free Software Foundation; either version 2.1 of the License, or 9 (at your option) any later version. See <http://www.gnu.org/licenses/>. 10 */ 11 12 // This file contains helpers recognising expression templates 13 14 #ifndef CXX_EXPRESSION_TRAITS_H 15 #define CXX_EXPRESSION_TRAITS_H 16 17 #include "mp.h" 18 #include "traits.h" 19 20 namespace flint { 21 namespace operations { 22 // These are the operation tags the expression class creates directly. 23 24 // unary operations 25 struct immediate { }; 26 struct negate { }; 27 struct complement { }; 28 29 // binary operations 30 struct plus { }; 31 struct minus { }; 32 struct times { }; 33 struct divided_by { }; 34 struct modulo { }; 35 struct shift { }; // left 36 struct binary_and { }; 37 struct binary_or { }; 38 struct binary_xor { }; 39 } // operations 40 41 namespace traits { 42 template<class T, class Enable = void> 43 struct is_expression : mp::false_ { }; 44 template<class T> 45 struct is_expression<T, typename T::IS_EXPRESSION_MARKER> : mp::true_ { }; 46 47 template<class T> 48 struct _is_immediate_expr 49 : _is_convertible< 50 typename basetype<T>::type::operation_t, 51 operations::immediate 52 > 53 { }; 54 55 // Compute if T is an expression, with operation "immediate" 56 template<class T, class Enable = void> 57 struct is_immediate_expr : _is_immediate_expr<T> { }; 58 template<class T> 59 struct is_immediate_expr<T, 60 typename mp::enable_if<mp::not_<is_expression<T> > >::type> 61 : mp::false_ { }; 62 63 // Compute if T is an immediate expression, *or not an expression at all* 64 template<class T> 65 struct is_immediate 66 : mp::or_<mp::not_<is_expression<T> >, is_immediate_expr<T> > { }; 67 68 // Compute if T is a non-immediate expression 69 template<class T> 70 struct is_lazy_expr 71 : mp::and_<is_expression<T>, mp::not_<is_immediate_expr<T> > > { }; 72 73 // Compute if Expr is an expression with prescribed evaluated type "T" 74 template<class Expr, class T, class Enable = void> 75 struct is_T_expr 76 : mp::equal_types<typename Expr::evaluated_t, T> { }; 77 template<class Expr, class T> 78 struct is_T_expr<Expr, T, 79 typename mp::disable_if<traits::is_expression<Expr> >::type> 80 : false_ { }; 81 82 // Decide if an expressing yielding From can be directly evaluated into To. 83 // To be further specialised! 84 template<class To, class From, class Enable = void> 85 struct can_evaluate_into : mp::false_ { }; 86 template<class T> 87 struct can_evaluate_into<T, T> : mp::true_ { }; 88 89 // Decide if we should use temporary merging 90 template<class Expr> 91 struct use_temporary_merging : mp::true_ { }; 92 } // traits 93 } // flint 94 95 #endif 96