Resorter - 1 year ago 75
C++ Question

``````#include <iostream>
#include <vector>
using namespace std;

void testfn(double* v1, double *v2, double *v3, int n);//I must use this function

class CLS{
private:
vector<double> v;
public:
CLS(vector<double> vin);
CLS operator+(CLS & A);
CLS operator*(CLS & A);
};

CLS::CLS(vector<double> vin)
{
v=vin;
}

CLS CLS::operator*(CLS &A){
//assuming the two vectors have the same length
vector<double> vtmp(v.size(),0);
testfn(&*A.v.begin(),&*v.begin(),&*vtmp.begin(),(int)A.v.size());
CLS C(vtmp);
return C;
}

CLS CLS::operator+(CLS &A){
//assuming the two vectors have the same length
vector<double> vtmp(v.size(),0);
testfn(&*A.v.begin(),&*v.begin(),&*vtmp.begin(),(int)A.v.size());
CLS C(vtmp);
return C;
}

void testfn(double* v1, double *v2, double *v3, int n)
{
for (int i=0;i<n;i++)
{
*v3=*v1+*v2;
++v1;
++v2;
++v3;
}
}

int main(){
vector<double> v1(100,1.0), v2(100,2.0), v3(100,0.0);
CLS C1(v1),C2(v2),C3(v3);
CLS C4=C1*(C1+(C2*C3+C2))*C1*C2*C3+C1+C2+C3;
return 0;
}
``````

I create class CLS and defined two operators + and *. I want to use these operators as simply as how we use + and * for integers and doubles. Therefore I have a test line in the main
`CLS C4=C1*(C1+(C2*C3+C2))*C1*C2*C3+C1+C2+C3;`
. However I get tons of errors when compiling this code using gcc. I am not familiar enough with the rules of operator overloading. How should I modify the definition (maybe just parameters?) of * and + so that
`CLS C4=C1*(C1+(C2*C3+C2))*C1*C2*C3+C1+C2+C3;`
is valid?

Supplements: I don't know how to use const parameter for operator+ and * , since the definition of these two operators involve another function
`testfn`
, whose parameters are double* instead of const double*. Further more, I do not want to change any part in the definition of
`testfn`
because in my real code it corresponds to a function in LAPACK which I absolutely have no right to change.

The unusual requirement to use the `testfn` with all params non-const is a bit weirds, but it's... umm.. reluctantly acceptable inacceptable for the case of complex expressions - the first two params of the testfn need to be `const double*`.

Rationale: C++ standard requires temporaries to be bound to `const references` - some interesting details here

@Resorter says:

"Thanks for letting me know and I would like to learn. But are you sure it solves my problem? I really want to solve this problem first."

[where it is 'move constructor' and 'move assignment']

The following "fish" assumes you have read/learnt fishing move constructor and move assign and the rules of 5/3/0,

Supplementary study material: copy elision - when the compiler is allowed to skip the copy/move constructors even when they would have side effects.

``````// some implementations
void testfn0(const double* v1, const double *v2, double *v3, int n) {
for(int i=0; i<n; i++) {
v3[i]=v1[i]+v2[i];
}
}

void testfn1(double* v1, double *v2, double *v3, int n) {
for(int i=0; i<n; i++) {
v3[i]=v1[i]*v2[i];
}
}

class CLS {
std::vector<double> v;
public:
// constructor taking a const reference
CLS(const std::vector<double>& in) : v(in) {
std::cout << "copy vec" << std::endl;
}

// extra constructor with rvalue reference: it will "canibalize" the parameter
CLS(std::vector<double>&& in) : v(in) {
std::cout << "move vec" << std::endl;
}

// Rule of 5 applied
// Copy constructor
CLS(const CLS& other) : v(other.v) {
std::cout << "copy CLS" << std::endl;
}
// Move constructor
CLS(CLS&& other) : v(std::move(other.v)) {
std::cout << "move CLS" << std::endl;
}
~CLS() { }

// Copy assgn
CLS& operator=(const CLS& o) {
this->v=o.v;
std::cout << "assgn CLS" << std::endl;
return *this;
}
// Move assgn
CLS& operator=(CLS&& other) {
this->v=std::move(other.v);
std::cout << "move CLS" << std::endl;
return *this;
}

// WILL NOT WORK WITHOUT const FOR COMPLEX EXPRESSIONS
//                       |
//              ----------
//              V
CLS operator+(const CLS& rhs) {
std::vector<double> vtmp(v.size(),0);
testfn0(&*rhs.v.begin(),&*v.begin(),&*vtmp.begin(),(int)rhs.v.size());

CLS ret(std::move(vtmp));
return ret;
}

// WILL NOT WORK WITHOUT const FOR COMPLEX EXPRESSIONS
//                       |
//              ----------
//              V
CLS operator*(const CLS& rhs) {
std::vector<double> vtmp(v.size(),0);
testfn1(&*rhs.v.begin(),&*v.begin(),&*vtmp.begin(),(int)rhs.v.size());

CLS ret(std::move(vtmp));
return ret;
}
};

int main() {
std::cout << "\n--- inits " << std::endl;
CLS a(std::vector<double>{1,2,3}); // move vec
CLS b(std::vector<double>{3,2,1}); // move vec

std::cout << "\n--- add " << std::endl;
CLS c=a+b; // move vec and 'silence' (copy elision)
std::cout << "\n--- mul " << std::endl;
CLS d=a*b; // move vec and 'silence' (copy elision)

std::cout << "\n--- copy " << std::endl;
CLS m=c; // Copy CLS - constructor

std::cout << "\n--- move " << std::endl;
CLS n=std::move(d); // Move CLS - constructor

std::cout << "\n--- assgn (d=c) and copy (x=c)" << std::endl;
CLS x=d=c;
}
``````
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download