/*************************************************************************** * Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht * * Copyright (c) QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XTENSOR_EXPRESSION_HPP #define XTENSOR_EXPRESSION_HPP #include #include #include #include #include #include #include "xlayout.hpp" #include "xshape.hpp" #include "xtensor_forward.hpp" #include "xutils.hpp" namespace xt { /*************************** * xexpression declaration * ***************************/ /** * @class xexpression * @brief Base class for xexpressions * * The xexpression class is the base class for all classes representing an expression * that can be evaluated to a multidimensional container with tensor semantic. * Functions that can apply to any xexpression regardless of its specific type should take a * xexpression argument. * * @tparam E The derived type. * */ template class xexpression { public: using derived_type = D; derived_type& derived_cast() & noexcept; const derived_type& derived_cast() const& noexcept; derived_type derived_cast() && noexcept; protected: xexpression() = default; ~xexpression() = default; xexpression(const xexpression&) = default; xexpression& operator=(const xexpression&) = default; xexpression(xexpression&&) = default; xexpression& operator=(xexpression&&) = default; }; /************************************ * xsharable_expression declaration * ************************************/ template class xshared_expression; template class xsharable_expression; namespace detail { template xshared_expression make_xshared_impl(xsharable_expression&&); } template class xsharable_expression : public xexpression { protected: xsharable_expression(); ~xsharable_expression() = default; xsharable_expression(const xsharable_expression&) = default; xsharable_expression& operator=(const xsharable_expression&) = default; xsharable_expression(xsharable_expression&&) = default; xsharable_expression& operator=(xsharable_expression&&) = default; private: std::shared_ptr p_shared; friend xshared_expression detail::make_xshared_impl(xsharable_expression&&); }; /****************************** * xexpression implementation * ******************************/ /** * @name Downcast functions */ //@{ /** * Returns a reference to the actual derived type of the xexpression. */ template inline auto xexpression::derived_cast() & noexcept -> derived_type& { return *static_cast(this); } /** * Returns a constant reference to the actual derived type of the xexpression. */ template inline auto xexpression::derived_cast() const& noexcept -> const derived_type& { return *static_cast(this); } /** * Returns a constant reference to the actual derived type of the xexpression. */ template inline auto xexpression::derived_cast() && noexcept -> derived_type { return *static_cast(this); } //@} /*************************************** * xsharable_expression implementation * ***************************************/ template inline xsharable_expression::xsharable_expression() : p_shared(nullptr) { } /** * is_crtp_base_of * Resembles std::is_base_of, but adresses the problem of whether _some_ instantiation * of a CRTP templated class B is a base of class E. A CRTP templated class is correctly * templated with the most derived type in the CRTP hierarchy. Using this assumption, * this implementation deals with either CRTP final classes (checks for inheritance * with E as the CRTP parameter of B) or CRTP base classes (which are singly templated * by the most derived class, and that's pulled out to use as a templete parameter for B). */ namespace detail { template