Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在“vector_binary_operation”类中处理对“expressions”的引用,而不使用不必要的副本_C++_Templates_C++11_C++14 - Fatal编程技术网

C++ 在“vector_binary_operation”类中处理对“expressions”的引用,而不使用不必要的副本

C++ 在“vector_binary_operation”类中处理对“expressions”的引用,而不使用不必要的副本,c++,templates,c++11,c++14,C++,Templates,C++11,C++14,我试图实现一个简单的vector类,该类使用,以避免vector w=x+y+z等表达式的实现效率低下(该实现将首先生成一个临时向量以容纳x+y,然后生成另一个向量,并添加z元素): 名称空间数学 { 模板 类表达式 { 公众: 自动大小()常量{ 返回静态_cast(*this).size(); } 自动运算符[](标准::大小\u t i)常量 { 如果(i>=size()) 抛出标准::长度_错误(“”); 返回静态_cast(*this)[i]; } 运算符E&({返回静态_cast(*

我试图实现一个简单的
vector
类,该类使用,以避免
vector w=x+y+z
等表达式的实现效率低下(该实现将首先生成一个临时向量以容纳
x+y
,然后生成另一个
向量
,并添加
z
元素):

名称空间数学
{
模板
类表达式
{
公众:
自动大小()常量{
返回静态_cast(*this).size();
}
自动运算符[](标准::大小\u t i)常量
{
如果(i>=size())
抛出标准::长度_错误(“”);
返回静态_cast(*this)[i];
}
运算符E&({返回静态_cast(*this);}
运算符E const&()const{return static_cast(*this);}
};//类表达式
模板
类向量
:公开表达
{
私人:
使用数据类型=标准::向量;
数据类型m_数据;
公众:
使用值_type=T;
使用分配器类型=分配器;
使用大小\类型=类型名称数据\类型::大小\类型;
使用差异类型=类型名称数据类型::差异类型;
使用reference=typename数据\ u type::reference;
使用const\u reference=typename data\u type::const\u reference;
使用指针=类型名数据\类型::指针;
使用常量指针=类型名数据类型::常量指针;
向量(大小\类型d)
:m_数据(d)
{ }
向量(std::初始值设定项\列表初始值)
:m_数据(初始)
{ }
模板
向量(表达式常量和表达式)
:m_数据(expression.size())
{
对于(size_type i=0;i;
私人:
使用向量_type=向量;
公众:
使用size\u type=typename vector\u type::size\u type;
使用差异类型=类型名向量类型::差异类型;
使用reference=typename向量\ u type::reference;
使用const_reference=typename vector_type::const_reference;
使用指针=类型名向量\类型::指针;
使用常量指针=类型名向量类型::常量指针;
向量二进制运算(表达式常量e1、表达式常量e2、二进制运算op)
:m_e1(e1),m_e2(e2),
m_op(op)
{
如果(e1.size()>0&&e2.size()>0&!(e1.size()==e2.size())
抛出std::逻辑_错误(“”);
}
大小\类型大小()常量{
返回m_e1.size();/==m_e2.size()
}
值类型运算符[](大小类型i)常量{
返回m_op(m_e1[i],m_e2[i]);
}
私人:
E1 m_E1;
E2 m_E2;
//E1施工与维护E1;
//E2 const&m_E2;
二进制操作mu op;
};//类向量_二进制_操作
模板
向量二进制运算
运算符+(表达式常量和e1、表达式常量和e2){
返回{e1,e2,std::plus()};
}
模板
向量二进制运算
运算符-(表达式常量和e1,表达式常量和e2){
返回{e1,e2,std::减号();
}
模板
向量二进制运算
运算符*(表达式常量和e1,表达式常量和e2){
返回{e1,e2,std::multiples()};
}
模板
向量二进制运算
运算符/(表达式常量和e1,表达式常量和e2){
返回{e1,e2,std::divides()};
}
模板
向量二进制运算
运算符/(表达式常量和表达式,T val){
返回{expr,detail::scalar(val),std::divides()};
}
模板
向量二进制运算
运算符*(T值、表达式常量和表达式){
返回{expr,detail::scalar(val),std::multiplies()};
}
模板
向量二进制运算
运算符*(表达式常量和表达式,tV
namespace math
{
    template<class E>
    class expression
    {
    public:
        auto size() const {
            return static_cast<E const&>(*this).size();
        }

        auto operator[](std::size_t i) const
        {
            if (i >= size())
                throw std::length_error("");
            return static_cast<E const&>(*this)[i];
        }

        operator E&() { return static_cast<E&>(*this); }
        operator E const&() const { return static_cast<E const&>(*this); }
    }; // class expression

    template<typename T, class Allocator = std::allocator<T>>
    class vector
        : public expression<vector<T>>
    {
    private:
        using data_type = std::vector<T, Allocator>;
        data_type m_data;

    public:
        using value_type = T;
        using allocator_type = Allocator;
        using size_type = typename data_type::size_type;
        using difference_type = typename data_type::difference_type;
        using reference = typename data_type::reference;
        using const_reference = typename data_type::const_reference;
        using pointer = typename data_type::pointer ;
        using const_pointer = typename data_type::const_pointer;

        vector(size_type d)
            : m_data(d)
        { }
        vector(std::initializer_list<value_type> init)
            : m_data(init)
        { }
        template<class E>
        vector(expression<E> const& expression)
            : m_data(expression.size())
        {
            for (size_type i = 0; i < expression.size(); ++i)
                m_data[i] = expression[i];
        }

        size_type size() const {
            return m_data.size();
        }
        
        value_type  operator[](size_type i) const { return m_data[i]; }
        value_type& operator[](size_type i)       { return m_data[i]; };
    }; // class vector

    namespace detail
    {
        template<typename T>
        class scalar
            : public expression<scalar<T>>
        {
        public:
            using value_type = T;
            using allocator_type = std::allocator<void>;
            using size_type = typename std::allocator<T>::size_type;
            using difference_type = typename std::allocator<T>::difference_type;
            using reference = typename std::allocator<T>::reference;
            using const_reference = typename std::allocator<T>::const_reference;
            using pointer = typename std::allocator<T>::pointer;
            using const_pointer = typename std::allocator<T>::const_pointer;

            scalar(value_type value)
                : m_value(value)
            { }

            size_type size() const {
                return 0;
            }

            operator value_type&() { return static_cast<value_type&>(*this); }
            operator value_type const&() const { return static_cast<value_type const&>(*this); }

            value_type  operator[](size_type i) const { return m_value; }
            value_type& operator[](size_type i) { return m_value; }

        private:
            value_type m_value;
        }; // class scalar

        template<class>
        struct is_scalar : std::false_type { };

        template<class T>
        struct is_scalar<scalar<T>> : std::true_type { };
    } // namespace detail

    template<class E1, class E2, class BinaryOperation>
    class vector_binary_operation
        : public expression<vector_binary_operation<E1, E2, BinaryOperation>>
    {
    public:
        using value_type = decltype(BinaryOperation()(typename E1::value_type(), typename E2::value_type()));
        using allocator_type = std::conditional_t<
            detail::is_scalar<E1>::value,
            typename E2::allocator_type::template rebind<value_type>::other,
            typename E1::allocator_type::template rebind<value_type>::other>;

    private:
        using vector_type = vector<value_type, allocator_type>;

    public:
        using size_type = typename vector_type::size_type;
        using difference_type = typename vector_type::difference_type;
        using reference = typename vector_type::reference;
        using const_reference = typename vector_type::const_reference;
        using pointer = typename vector_type::pointer;
        using const_pointer = typename vector_type::const_pointer;

        vector_binary_operation(expression<E1> const& e1, expression<E2> const& e2, BinaryOperation op)
            : m_e1(e1), m_e2(e2),
              m_op(op)
        {
            if (e1.size() > 0 && e2.size() > 0 && !(e1.size() == e2.size()))
                throw std::logic_error("");
        }

        size_type size() const {
            return m_e1.size(); // == m_e2.size()
        }

        value_type operator[](size_type i) const {
            return m_op(m_e1[i], m_e2[i]);
        }

    private:
        E1 m_e1;
        E2 m_e2;
        //E1 const& m_e1;
        //E2 const& m_e2;
        BinaryOperation m_op;
    }; // class vector_binary_operation

    template<class E1, class E2>
    vector_binary_operation<E1, E2, std::plus<>>
    operator+(expression<E1> const& e1, expression<E2> const& e2) {
        return{ e1, e2, std::plus<>() };
    }
    template<class E1, class E2>
    vector_binary_operation<E1, E2, std::minus<>>
    operator-(expression<E1> const& e1, expression<E2> const& e2) {
        return{ e1, e2, std::minus<>() };
    }
    template<class E1, class E2>
    vector_binary_operation<E1, E2, std::multiplies<>>
    operator*(expression<E1> const& e1, expression<E2> const& e2) {
        return{ e1, e2, std::multiplies<>() };
    }
    template<class E1, class E2>
    vector_binary_operation<E1, E2, std::divides<>>
    operator/(expression<E1> const& e1, expression<E2> const& e2) {
        return{ e1, e2, std::divides<>() };
    }

    template<class E, typename T>
    vector_binary_operation<E, detail::scalar<T>, std::divides<>>
    operator/(expression<E> const& expr, T val) {
        return{ expr, detail::scalar<T>(val), std::divides<>() };
    }
    template<class E, typename T>
    vector_binary_operation<E, detail::scalar<T>, std::multiplies<>>
    operator*(T val, expression<E> const& expr) {
        return{ expr, detail::scalar<T>(val), std::multiplies<>() };
    }
    template<class E, typename T>
    vector_binary_operation<E, detail::scalar<T>, std::multiplies<>>
    operator*(expression<E> const& expr, T val) {
        return{ expr, detail::scalar<T>(val), std::multiplies<>() };
    }
} // namespace math
vector a;
vector b;
auto c = a + b;
template<typename E1, typename E2>
auto operator+(E1&& e1, E2&& e2)
{
     using value_type = decltype(e1[0] + e2[0]);
     return vector_binary_operation<E1, E2, std::plus<value_type> >
                   {std::forward<E1>(e1), std::forward<E2>(e2), std::plus<value_type>{}};
}
auto c = a + b;
auto d = (a + b) + b;