mercredi 1 mars 2017

Move semantics with overloaded operators: how to make them work together?

I'm trying to use move semantics with overloaded operators:

namespace MTensor {
typedef std::vector<double> Tensor1DType;

class Tensor1D {
private:
  Tensor1DType data;
public:
  Tensor1D() {};
  Tensor1D(const Tensor1D& other)=default;
  Tensor1D(Tensor1D&& other)=default;
  ~Tensor1D()=default;
  Tensor1D& operator=(Tensor1D&& other)=default;
  Tensor1D& operator=(Tensor1D const& other)=default;
  Tensor1D(const std::initializer_list<double>&  valuesList) {
    insert(valuesList);
  }
  int size() const {
    return data.size();
  };
  void insert(double value) {
    data.push_back(value);
  }
  void insert(const std::initializer_list<double>&  valuesList) {
    data.insert( data.end(), valuesList.begin(), valuesList.end() );
  }
  Tensor1DType operator()() const {
    return data;
  }
  double operator() (int i) const {
    if(i>data.size()) {
      std::cout << "index must be within vector dimension" << std::endl;
      exit(1);
    }
    return data[i];
  }
  void set(int i, double v) {
    if(i>data.size()) {
      std::cout << "index must be within vector dimension" << std::endl;
      exit(1);
    }
    data.at(i) = v;
  }
  Tensor1D operator*=(const Tensor1D& t1) = delete;
  Tensor1D operator*=(Tensor1D&& t1) {
    int i=0;
    for(auto v1 : t1()) {
      set(i,v1 * data.at(i));
      i++;
    }
  return *this;
  }
  Tensor1D operator*=(double scalar) {
    int i=0;
    for(auto value : data) {
      set(i, data.at(i) * scalar);
      i++;
    }
    return *this;
  }
  static void printTensor(Tensor1DType const& info) {
    for(double e : info) {
      std::cout << e << "," << std::endl;
    }
  }
  void printTensor() const {
    printTensor(data);
  }
};
} // end of namespace MTensor

In main.cpp:

double operator*(MTensor::Tensor1D t1, MTensor::Tensor1D t2) { 
  if(t1.size()!=t2.size()) {
    std::cout << "The two vectors must have the same number of elements";
    exit(1);
  }
  double dotproduct = 0.0;
  int i=0;
  for(auto v1 : t1()) {
    dotproduct += (v1 * t2(i));
    i++;
  }
  return dotproduct;
}
MTensor::Tensor1D operator+(MTensor::Tensor1D t1, MTensor::Tensor1D t2) {
  if(t1.size()!=t2.size()) {
    std::cout << "The two vectors must have the same number of elements";
    exit(1);
  }
  MTensor::Tensor1D tensor;
  int i =0;
  for(auto v : t1()) {
    tensor.insert(v + t2(i));
    i++;
  }
  return tensor;
}

int main() {
  MTensor::Tensor1D t1 = {1,2,3};
  MTensor::Tensor1D t2 = {4,5,6};
  std::cout << "t1 *= std::move(t2) : " << std::endl;
  t1 *= std::move(t2);
  std::cout << "t1:" << std::endl;
  t1.printTensor();
  std::cout << "t2:" << std::endl;
  t2.printTensor();
  MTensor::Tensor1D t5 = {1,2,3};
  MTensor::Tensor1D t6 = {4,5,6};
  double t5t6_dp = t5 * t6;
  std::cout << std::endl;
  std::cout << "t5t6_dp = t5 * t6 = " << t5t6_dp << std::endl;
  std::cout << "t5:" << std::endl;
  t5.printTensor();
  std::cout << "t6:" << std::endl;
  t6.printTensor();
  double t5t6_dpM = std::move(t5) * std::move(t6);
  std::cout << "t5t6_dpM = std::move(t5) * std::move(t6) = " << t5t6_dpM <<     
    std::endl;
  std::cout << "t5:" << std::endl;
  t5.printTensor();
  std::cout << "t6:" << std::endl;
  t6.printTensor();
  std::cout << std::endl;

  return 0;
}

Executing:

t1:1,2,3,
t2:4,5,6,
t1 *= std::move(t2) :
t1:4,10,18,
t2:4,5,6,

t5t6_dp = t5 * t6 = 32
t5:1,2,3,
t6:4,5,6,
t5t6_dpM = std::move(t5) * std::move(t6) = 32
t5:
t6:

My question is: how to fix the overloaded operator *= within the class in order to have

t1 *= std::move(t2); 

t1={1,2,3} 

and

t2 ={} 

(nullptr because of the move semantics)

like the operator*,which is working properly?

Aucun commentaire:

Enregistrer un commentaire