{! public:! minus(! const std::shared_ptr< llvm::LLVMContext > &context_,! const std::shared_ptr< ir_builder_t > &ir_builder_,! const expression &left_, const expression &right_! ) : context( context_ ), ir_builder( ir_builder_ ), left( left_ ), right( right_ ) {}! template< typename Left, typename Right >! expression operator()(! const Left &, const Right &,! typename boost::enable_if<! boost::mpl::and_<! type_traits::meta::is_arithmetic_convertible<! Left! >,! type_traits::meta::is_arithmetic_convertible<! Right! >! >! >::type* = 0! ) const {! const auto result_type =! type_traits::usual_arithmetic_conversion(! left.type(), right.type()! );! const expression converted_left = implicit_cast(! context, ir_builder, result_type, left! );! const expression converted_right = implicit_cast(! context, ir_builder, result_type, right! );! const auto llvm_type = get_llvm_type(! context, result_type! );! const std::shared_ptr< llvm::LLVMContext > &context_ =! context;! if( type_traits::is_floating_point( result_type ) ) {! return expression(! result_type, llvm_type,! std::shared_ptr< llvm::Value >(! ir_builder->CreateFSub(! converted_left.llvm_value().get(),! converted_right.llvm_value().get()! ),! [context_]( llvm::Value* ){}! )! );! }! else {! return expression(! result_type, llvm_type,! std::shared_ptr< llvm::Value >(! ir_builder->CreateSub(! converted_left.llvm_value().get(),! converted_right.llvm_value().get()! ),! [context_]( llvm::Value* ){}! )! );! }! }! template< typename Left, typename Right >! expression operator()(! const Left &, const Right &,! typename boost::enable_if<! boost::mpl::and_<! type_traits::meta::is_pointer< Left >,! type_traits::meta::is_arithmetic_convertible<! Right! >! >! >::type* = 0! ) const {! const expression converted_index = implicit_cast(! context, ir_builder,! type_traits::integral_promotion( right.type() ),! right! );! const auto pointer_type = type_traits::remove_const(! left.type()! );! const auto llvm_type = get_llvm_type(! context, pointer_type! );! const std::shared_ptr< llvm::LLVMContext > &context_ =! context;! return expression(! pointer_type, llvm_type,! std::shared_ptr< llvm::Value >(! ir_builder->CreateInBoundsGEP(! left.llvm_value().get(),! ir_builder->CreateNeg(! converted_index.llvm_value().get()! )! ),! [context_]( llvm::Value* ){}! )! );! }! template< typename Left, typename Right >! expression operator()(! const Left &, const Right &,! typename boost::enable_if<! boost::mpl::not_<! boost::mpl::or_<! boost::mpl::and_<! type_traits::meta::is_arithmetic_convertible<! Left! >,! type_traits::meta::is_arithmetic_convertible<! Right! >! >,! boost::mpl::and_<! type_traits::meta::is_pointer< Left >,! type_traits::meta::is_arithmetic_convertible<! Right! >! >! >! >! >::type* = 0! ) const {! throw exceptions::invalid_expression();! }! private:! std::shared_ptr< llvm::LLVMContext > context;! std::shared_ptr< ir_builder_t > ir_builder;! expression left;! expression right;! };! }! expression minus(! const std::shared_ptr< llvm::LLVMContext > &context,! const std::shared_ptr< ir_builder_t > &ir_builder,! const expression &left_expr,! const expression &right_expr! ) {! const expression left = remove_reference(! context, ir_builder, left_expr! );! const expression right = remove_reference(! context, ir_builder, right_expr! );! return apply_visitor(! node::minus( context, ir_builder, left, right ),! left.type(), right.type()! );! EMBNCEBTSDDPNQJMFNJOVTDQQ