Reputation: 317
#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+(const CLS & A)const;
};
CLS::CLS(vector<double> vin)
{
v=vin;
}
CLS CLS::operator+(const CLS &A)const{
//assuming the two vectors have the same length
vector<double> vtmp(v.size(),0);
testfn(&*v.begin(),&*A.v.begin(),&*vtmp.begin(),(int)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);
CLS C1(v1),C2(v2);
CLS C3=C1+C2;
return 0;
}
In the above sample code, I create a class CLS and an overloaded operator +. In the definition of +, I call a function whose parameters contain double*
pointers. In my real code this function is replaced by a function in LAPACK so I can not change it. Therefore when I ask this question, I assume we do not change anything about testfn
and the fact that we must use testfn
to define operator +. But I got the following error messages. How can I get rid of them?
test1.cpp: In member function 'CLS CLS::operator+(const CLS&) const':
test1.cpp:25:66: error: invalid conversion from 'const double*' to 'double*' [-fpermissive]
testfn(&*v.begin(),&*A.v.begin(),&*vtmp.begin(),(int)v.size());
^
test1.cpp:6:6: note: initializing argument 1 of 'void testfn(double*, double*, double*, int)'
void testfn(double* v1, double *v2, double *v3, int n);
^
test1.cpp:25:66: error: invalid conversion from 'const double*' to 'double*' [-fpermissive]
testfn(&*v.begin(),&*A.v.begin(),&*vtmp.begin(),(int)v.size());
^
test1.cpp:6:6: note: initializing argument 2 of 'void testfn(double*, double*, double*, int)'
void testfn(double* v1, double *v2, double *v3, int n);
^
make: *** [test1.o] Error 1
A follow up question (I can not post two questions in 90 minutes so I just add it behind this one)
#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;
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;
. However I get tons of errors when compiling this code. 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;
is valid?
Upvotes: 0
Views: 279
Reputation: 3651
Ideally, you would change the parameters of testfn
to all be const
. You have said in the comments that isn't an option. From your definitions here there isn't really a reason they can't be changed, but I'll ignore that for now.
If you need the +operator to remain const, you could create deep copies of v
and A
to pass in to test_fn
.
CLS CLS::operator+(const CLS & A) const
{
//assuming the two vectors have the same length
vector<double> vtmp(v.size(), 0);
vector<double> v1 = v;
vector<double> v2 = A.v;
testfn(&*v1.begin(), &*v2.begin(), &*vtmp.begin(), (int)v.size());
CLS C(vtmp);
return C;
}
If copies are expensive, and you are sure testfn
doesn't modify the inputs, you can const_cast
the inputs instead.
Another possibility would be to remove all the const qualifiers on the +operator:
CLS CLS::operator+(CLS & A)
{
//assuming the two vectors have the same length
vector<double> vtmp(v.size(), 0);
testfn(&*v.begin(), &*A.v.begin(), &*vtmp.begin(), (int)v.size());
CLS C(vtmp);
return C;
}
because testfn
takes pointers that aren't const, you don't really have any guarantee that it isn't changing the values inside of v
or A
.
Upvotes: 1
Reputation: 596352
Ideally, you should redeclare testfn()
to make its read-only parameters be const
:
void testfn(const double* v1, const double *v2, double *v3, int n);
But, if that is not an option for you, you could at least have operator+
simply const_cast
away the constness when using A.v
:
CLS CLS::operator+(const CLS &A) const
{
//assuming the two vectors have the same length
vector<double> vtmp(v.size(), 0);
// if the vectors are empty, the begin() iterators
// will match the end() iterators, and dereferencing
// an end() iterator is undefined behavior! So make
// sure the vectors are not empty...
if (!v.empty())
testfn(&*v.begin(), &*const_cast<CLS&>(A).v.begin(), &*vtmp.begin(), (int)v.size());
return CLS(vtmp);
}
BTW, using &*begin()
is pretty ugly, you could use std::vector::operator[]
instead:
CLS CLS::operator+(const CLS &A) const
{
//assuming the two vectors have the same length
vector<double> vtmp(v.size(), 0);
// if the vectors are empty, accessing any elements
// is undefined behavior! So make sure the vectors
// are not empty...
if (!v.empty())
testfn(&v[0], &(const_cast<CLS&>(A).v[0]), &vtmp[0], (int)v.size());
return CLS(vtmp);
}
Or, if you are using C++11 or later, use std::vector::data()
instead:
CLS CLS::operator+(const CLS &A) const
{
//assuming the two vectors have the same length
vector<double> vtmp(v.size(), 0);
// if the vectors are empty, accessing any elements
// is undefined behavior! So make sure the vectors
// are not empty...
if (!v.empty())
testfn(v.data(), const_cast<CLS&>(A).v.data(), vtmp.data(), (int)v.size());
return CLS(vtmp);
}
Upvotes: 0