2016-09-17 8 views
0

У меня есть некоторые странные проблемы, связанные с ленивым назначением и добавлением, как указано в https://eigen.tuxfamily.org/dox/TopicInsideEigenExample.html.Ошибка при реализации ленивого назначения в C++

Код

template<typename Derived> class Base; 
template<typename Derived, typename OtherDerived> class SumOp; 

template<typename Derived, typename OtherDerived> 
class SumOp: public Base<SumOp<Derived, OtherDerived>>{ 
public: 
    Derived & lhs; 
    OtherDerived & rhs; 

    SumOp(Derived & lhs_, OtherDerived & rhs_):lhs(lhs_), rhs(rhs_){} 
    double packet(size_t index, Base<OtherDerived>& src){ 
     return lhs.packet(index)+ rhs.packet(index); 
    } 
}; 
template<typename Derived, typename OtherDerived> 
struct Assign{ 
    static Derived& run(Derived & dst, OtherDerived & src){ 
     size_t length = dst.size(); 
     for (size_t index =0; index < length; index++){ 
      dst.copyPacket(index, src); 
     } 
     return dst; 
    } 
}; 


template<typename Derived> 
class Base{ 
public: 
    Base(){} 
    Derived& derived(){ 
     return *static_cast<Derived*>(this); 
    } 

    const Derived& derived() const{ 
     return *static_cast<const Derived*>(this); 
    } 

    template<typename OtherDerived> 
      SumOp<Derived,OtherDerived> operator+(Base<OtherDerived> & other){ 
       return SumOp<Derived, OtherDerived>(this->derived(), other.derived()); 
    } 

    template<typename OtherDerived> 
     Derived & operator=(Base<OtherDerived>& other){ 
     return Assign<Derived, OtherDerived>::run(derived(), other.derived()); 
    } 
    template<typename OtherDerived> 
      void copyPacket(size_t index, Base<OtherDerived> & other){ 
     derived().writePacket(index, other.derived().packet(index)); 
    } 
}; 


class Vector: public Base<Vector> { 
public: 
    double * data; 
    size_t nRow; 

    Vector(size_t nRow_):nRow(nRow_){ 
     data = (double *)malloc(sizeof(double)*nRow); 
    } 
    ~Vector(){ 
     free(data); 
    } 
    template<typename OtherDerived> 
      Vector& operator=(Base<OtherDerived>& other){ 
     return Base<Vector>::operator=(other); 
    } 
    size_t size(){ 
     return nRow; 
    } 
    void writePacket(size_t index, double src){ 
     data[index] = src; 
    } 
    double packet(size_t index){ 
     return data[index]; 
    } 
}; 

Короче говоря, проблема заключается в том, когда я называю operator= в векторном классе, где компилятор жалуется, что я прошел значение левого Base<SumOp<Vector, Vector>> оператору вместо SumOp<Vector, Vector>&. Последний из которых создается при вызове operator+, который возвращает SumOp<Vector, Vector>.

Ошибка компилятора

no known conversion for argument 1 from ‘SumOp<Vector, Vector>’ to ‘Base<SumOp<Vector, Vector> >&’ 

Я не знаю, почему реализация в Эйгеном порядке и как решить эту проблему.

Спасибо за помощь.

EDIT

Проблема возникает, когда я звоню следующие функции

void test_vector(){ 
    Vector a(10), b(10), c(10); 
    for (int i=0;i<10;i++){ 
     a.data[i]=1.0; 
     b.data[i]=1.0; 
    } 
    //This is very it goes wrong 
    c = a+b; 


    for (int i =0 ; i<10;i++){ 
     std::cout << c.data[i] << std::endl; 
    } 

}; 

С г ++ - 6 ошибка читает

invalid initialization of non-const reference of type ‘Base<SumOp<Vector, Vector> >&’ from an rvalue of type ‘Base<SumOp<Vector, Vector> >’ 
    c = a+b; 
     ~^~ 
In file included from /home/ran/Desktop/experiment/PointerMatrix/vector.cpp:6:0: 
/home/ran/Desktop/experiment/PointerMatrix/vector.h:76:21: note: initializing argument 1 of ‘Vector& Vector::operator=(Base<OtherDerived>&) [with OtherDerived = SumOp<Vector, Vector>]’ 
      Vector& operator=(Base<OtherDerived>& other){ 
+0

я не могу [воспроизвести] (http://coliru.stacked-crooked.com/a/20b82584350dab32) ваша проблема, как GCC 6.1 и Clang 3,8 – WhiZTiM

+0

Попробую с gcc6 –

+0

Уже сделал ~ Спасибо очень для напоминания –

ответ

3

Проблема в том, что аргументы, чтобы ваш operator функции не являются константными ссылками. operator+ возвращает временный объект SumOp, который не может быть передан как неконстантная ссылка. (Некоторые компиляторы могут поддерживать это как расширение.)

Изменение параметров, которые должны быть const &, должно устранить эту проблему.

+0

Точно! Я думал, что могу обойти проблему const, но я ошибаюсь ....... –

+0

Стоит упомянуть о пересылке ссылок на этот случай –