класс шаблона многомерного массива с шаблонами выражений - PullRequest
0 голосов
/ 04 ноября 2018

Я пытаюсь понять шаблоны выражений, реализуя свой собственный класс многомерного массива. По сути, я выделяю непрерывный кусок памяти, а затем вычисляю смещения с помощью оператора ().

Теперь я хочу перегрузить +, /, *, - шаблонами выражений. Пример, проиллюстрированный в Википедии, довольно показателен, но предполагает, что блок данных имеет тип double. Я хотел бы иметь тип данных в качестве параметра шаблона. Я пытался реализовать это, но я всегда терплю неудачу. Это код до сих пор:

    namespace ader{

    template<class E, typename T> class vexp{
        inline unsigned size()const{return static_cast<E const&>(*this).size();};
        inline T operator[](const unsigned &i) const{ return static_cast<E const&>(*this)[i];}
    };

// ***************************************************************************** // 

    template<class E1, class E2, typename T>
        class vsum:
        public vexp<vsum<E1,E2,T>,T>{
        const E1 &_u;
        const E2 &_v;
        public:
        vsum(const E1 &u, const E2 &v): _u(u), _v(v){};
        inline T operator[](const unsigned &i)const {return _u[i] + _v[i];};
        inline unsigned size()const{return _u.size();};
    };


// ***************************************************************************** // 


    template<typename T, unsigned nDer> class aDer: public ader::vexp<aDer<T,nDer>,T>{
        protected:
        unsigned n;
        T d[nDer+1];

        public:
        unsigned size()const{return n;};

        T  operator[](const unsigned &i)     {return d[i];};
        T &operator[](const unsigned &i)const{return d[i];};

        aDer():n(nDer), d{0}{};
        aDer(const T &in): n(nDer), d{0}{d[0] = in;};
        aDer(const T &in, const unsigned &idx): n(nDer), d{0}{d[0] = in; d[idx+1] = T(1);};
        template<template<typename,unsigned> class U> aDer(const vexp<U<T,nDer>,T> &in){
            for(unsigned ii=0; ii<=nDer; ++ii) d[ii] = in[ii];
        }
    };

    template< class E1, class E2, typename T>
        vsum<E1,E2,T> operator+(const E1 &u, const E2 &v){return vsum<E1,E2,T>(u,v);};


};

Сообщение об ошибке:

main2.cc: In function ‘int main()’:
main2.cc:15:27: error: no match for ‘operator+’ (operand types are ‘ader::aDer<float, 2>’ and ‘ader::aDer<float, 2>’)
ader::aDer<float,2> c= a+b;

Что-то явно не так в коде?

EDIT1: содержимое main2.cc:

#include "aut2.h"
#include <iostream>

using namespace std;

int main(){

    ader::aDer<float,2> a(1.220334, 1);
    ader::aDer<float,2> b(3.0, 0);

    ader::aDer<float,2> c= a+b;

    cerr<<c[0]<<endl;

}

1 Ответ

0 голосов
/ 04 ноября 2018

Ваш operator+ имеет недопустимый параметр T. Вам нужно избавиться от этого параметра и вывести T из E1 и E2.

Один из способов добиться этого - определить operator+ следующим образом:

template <class E1, class E2>
auto operator+(const E1 &u, const E2 &v) -> vsum<E1, E2, decltype(u[0] + v[0])>
{
    return { u,v };
}

Другим способом было бы избавиться от параметра T во всех ваших классах, используя вместо этого auto и decltype(auto):

template <class E> class vexp {
    ...
    inline decltype(auto) operator[](const unsigned &i) const { return static_cast<E const&>(*this)[i]; }
};

В приведенном выше коде operator[] вернет любой тип E::operator[], который возвращается.

Обратите внимание, что decltype(auto) и auto без заданного типа возвращаемого значения являются функцией C ++ 14.

...