I'm trying to create an overridden operator function using both const parameters, but I can't figure out how to do it. Here is a simple example:
class Number
{
Number()
{
value = 1;
};
inline Number operator + (const Number& n)
{
Number result;
result.value = value + n.value;
return result;
}
int value;
}
What I am trying to do here is pass in two arguments into the addition function that are both const and return the result without changing anything in the class:
const Number a = Number();
const Number b = Number();
Number c = a + b;
Is this possible and how would I go about doing this?
Thanks,
Dan
inline is understood in class declarations so you don't need to specify it.
Most idiomatically, you would make operator+ a non-member function declared outside the class definition, like this:
Number operator+( const Number& left, const Number& right );
You might need to make it a friend of the class if it needs access to Number's internals.
If you have to have it as a member function then you need to make the function itself const:
Number operator+( const Number& n ) const
{ // ...
For classes like Number, operator+ is typically implemented in terms of operator+= as usually you want all the usual operators to work as expected and operator+= is typically easier to implement and operator+ tends not to lose any efficiency over implementing it separately.
Inside the class:
Number& operator+=( const Number& n );
Outside the class:
Number operator+( const Number& left, const Number& right )
{
return Number( left ) += right;
}
or even:
Number operator+( Number left, const Number& right )
{
return left += right;
}
class Number
{
Number()
{
value = 1;
};
inline Number operator + (const Number& n) const
{
Number result;
result = value + n.value;
return result;
}
int value;
}
How about:
inline Number operator + (const Number& n) const
While I feel the previous answers are good enough, I believe some clarification is needed.
Operators come (usually) in two flavors
The first being the non-member functions, the second being the member function whose parameter is the "right operand" of the operation and which usually returns the current modified object.
For example, imagine there's an operator § for a class T. It could be written either as a non-member function:
T operator § (const T & lhs, const T & rhs)
{
T result ;
// do the lhs § rhs operation, and puts the result into "result"
return result ;
}
or as a member function:
T & T::operator § (const T & rhs)
{
// do the "this § rhs" operation, and puts the result into "this"
return *this ;
}
or even (very unusually) as another member function:
T T::operator § (const T & rhs) const
{
T result ;
// do the "this § rhs" operation, and puts the result into "result"
return result ;
}
Usually, you should prefer the non-member function, if only because you should not declare it friend. Thus, using non-member non-friend function enhance the encapsulation of your object.
Disclaimer: There are other flavors, but I'm limiting myself to arithmetic operators like +, *, /, -, etc. here, as well as "credible" operator prototypes.
Analyse your use of the operator
In the case of +:
Each operand needs to be constant because a = b + c must not change b, nor c.
You can accumulate +, like in a = b + c + d + e, so temporaries must exist.
T operator § (const T & lhs, const T & rhs)
{
T result ;
// do the lhs § rhs operation, and puts the result into "result"
return result ;
}
In the case of +=:
You know the left operand A (from A += B) will be modified.
You know the left operand A (from A += B) is its own result.
So you should use:
T & T::operator += (const T & rhs)
{
// do the "this § rhs" operation, and puts the result into "this"
return *this ;
}
As always, premature optimization is the root of all evil
I've seen this kind of code in production code so, it does happen:
T & operator + (const T & lhs, const T & rhs)
{
static T result ; // result is STATIC !!!!
// do the lhs + rhs operation, and puts the result into "result"
return result ;
}
The author hoped to economize one temporary. With this kind of code, writing a = b + c + d leads to interesting (and wrong) results.
^_^
Last but not least
I did write a list of operator overloading prototypes on this page. The page is still under construction, but its main use (easy to copy/paste working prototypes) can be quite useful...
Related
I'm curious if there are possibilities outside of a simple function or construct. Though a slight simplification of my code it would add up to a lot to not have to write in the conversion of a percentage back and forth between displaying and calculating.
You cannot create a brand new postfix operator out of thin air. The list, syntax, and precedence of the operators is set into stone.
However, there is something in the language that just might be close enough for your needs: User-defined literals
constexpr long double operator ""_pct(unsigned long long int v) {
return (long double)v / 100;
}
void foo() {
double x = 30_pct;
}
That can only be used on literal values, as opposed to arbitrary expressions. But again, that's as good as you're going to get.
The best way is to define a type which will handle percentage.
class Percentage {
public:
constexpr Percentage(int); // use explicit? This depends on requirements
constexpr Percentage(unsigned long long int);
constexpr Percentage(double);
constexpr operator int() const;
constexpr operator double() const;
constexpr Precentage fromRatio(double x) {
return {x * 100};
}
private:
.....
};
// custom literal is just sugar coating
Percentage operator ""_pct(unsigned long long int v) {
return Percentage(v);
}
As well as user-defined literals already discussed, you could use a percentage value type. Something like:
class Percent
{
public:
constexpr Percent(double v) : val(v) {}
constexpr double value() const { return val; }
constexpr double scale() const { return val / 100; }
/** \brief Multiply a number by its scaled value
* Can also be done as a free function
*/
double operator *(double other) const
{
return other * scale();
}
// other operators
private:
double val;
};
std::ostream& operator <<(std::ostream& os, Percent p)
{
os << p.value() << '%';
return os;
}
Using constexpr correctly, you should be able to get the result you want without any runtime overhead.
Let us consider
we have created our own class Array. And now we want to overload "+" operator so that if:
Array a(5), b(3);
Array c = a + b;
it simply glues together a array and b array and we get a c array with length 5+3=8.
Now, I have realised this case writing in me Array.cpp file:
Array Array::operator+(const Array &Right)
{
Array temp_A(m_iCurInd+Right.m_iCurInd);
// here some stuff, not important to the quastion//
return temp_A;
}
And everything is fine.
But what if I want to :
Array a(5);
Array c = a + 2;
Array d = 2 + a;
So that d and c had lengths 6, with "2" in the beginning and in the end respectively?
I have tried
to realise the firs case, so in Array.h file it was such a line:
Array operator+(const int &value); //a+2
And in Array.cpp:
Array Array::operator+(const int &value)
{
Array temp_A(m_iCurInd+1);
// here some stuff, not important to the quastion//
return temp_A;
}
But it doesn't compiles, because it doesn't likes the types (particulary const int & I think). How shell I make it? Shell it be:
Array int::operator+(const Array &Right){
....
}
for the "2+a" case or something simmilar? Please advise me.
You might do this:
class Array
{
// ...
// Insert an Element
public:
void prepend(int);
void append(int);
// Append an Array
void append(const Array&);
// ...
};
inline Array operator + (const Array& a, const Array& b) {
Array result(a);
result.append(b);
return result;
}
inline Array operator + (const Array& a, int b) {
Array result(a);
result.append(b);
return result;
}
inline Array operator + (int a, const Array& b) {
Array result(b);
result.prepend(a);
return result;
}
You would define operator+ as a non-member function to support mixed-mode arithmetic.
Array operator+( const Array &arr1, const Array &arr2 )
and then provide appropriate single argument constructor for the types you want to support mixed-mode arithmetic.
To allow the syntax Array + int you have two options: Create a member function overload of operator+ where the parameter it takes is an integer, or create a free operator+ whose parameters are Array and int respectively. It looks like you've done it correctly for the member function overload, but to make sure, it should look like this:
class Array
{
// ...
Array operator+(int rhs)
{
// ...
}
};
Now Array + int should work. If it doesn't, you've done something wrong inside the function.
To allow the syntax int + Array you need a free operator function because the member function won't overload int for the left side:
Array operator+(int lhs, Array const& rhs)
{
return rhs + lhs;
}
rhs + lhs calls the member function overload Array::operator+().
So for class this week I have to use a set to read in the Declaration of Independence and the US Constitution from a .txt file, store them in sets, and overload operator* to find and return the intersection of the two sets.
Reading everything in is not a problem, neither is finding out the intersection in the sets. What I'm having a lot of trouble with is overloading operator*. I keep getting two errors:
no operator "*" matches these operands
and
binary "*":'std::set<_Kty>' does not define this operator or a conversion to a type acceptable to the predefined operator
Here is my code so far:
From main:
Reader r;
std::set<std::string> d, c;
d = r.GetDeclaraton();
c = r.GetConstitution();
Set dec(d), con(c);
Set intersection = dec * con;
The errors are coming from that last line of main.
From Set.h
class Set
{
public:
std::set<std::string> s;
Set(void);
Set(std::set<std::string> set)
{
s = set;
}
~Set(void);
std::set<std::string> operator* (const std::set<std::string> &rhs)
{
std::set<std::string> newset;
std::set<std::string>::iterator rhsiter = rhs.begin(), result;
while (rhsiter != rhs.end())
{
result = s.find(*rhsiter++);
if (result != rhs.end())
{
newset.insert(*result);
}
}
return newset;
}
};
You need
Set operator* (const Set &rhs) const
because this is a binary operator with two Sets as arguments. Your attempt would only work if your Set was deriving std::set.
The return type here is Set. It makes more sense to be the same as the input arguments, and this is also consistent with your usage in main. So in this case you need to modify the definition to construct and return a Set instead of an std::set (or rather you need not because an std::set can be implicitly converted to a Set).
Note also I made operator* a const member function, since it's not modifying its object.
operator* is defined in your custom Set so the left-hand-side argument must be a Set, but in dec.s * con.s you're using .s which accesses the member std::set fields, and there's no operator* defined for a left-hand Set and rhs-hand std::set.
You could change to dec * con.s, but it'd be better to change the operator* rhs argument to a const Set& too, and use rhs.s inside the operator... less confusing!
In my opinion its better to write a global or friend operator. Also, for intersection I would use the & operator, for union the | or + operator while, difference: -...
Why global operators? With global operators you can write an operator for your class even if the left operand is not your class. For example in case of a matrix class you can easily write a global operator that multiplies together a float and a matrix while as a matrix member operator you could write only an operator where your matrix is on the left.
Example:
template <typename T>
inline std::set<T> intersection(const std::set<T>& smaller, const std::set<T>& larger)
{
std::set<T> result;
for (auto it=smaller.begin(),eit=smaller.end(); it!=eit; ++it)
{
if (larger.find(*it) != larger.end())
result.insert(*it);
}
return result;
}
template <typename T>
inline std::set<T> operator & (const std::set<T>& a, const std::set<T>& b)
{
if (a.size() < b.size())
return intersection(a, b);
return intersection(b, a);
}
class Set
{
public:
std::set<std::string> s;
Set() {}
Set(std::set<std::string> _s) : s(_s) {}
friend Set operator & (const Set& a, const Set& b)
{
return Set(a.s & b.s);
}
};
int test()
{
std::set<std::string> s, t;
s.insert("aa");
s.insert("bb");
t.insert("bb");
t.insert("cc");
std::set<std::string> u(s & t);
Set ss(s), st(t);
Set result(ss & st);
return 0;
}
Have this code in a simple class Time composed of two integers (day/hour) for an arduino project.
bool operator <= (const Time& other) const{
return (day <= other.day && hour <= other.hour);
}
Although I do have an almost identical (and working) other class which uses the same syntax with the same non-static form... I'm getting the following errors :
error: non-member function ‘bool operator<=(const Time&)’ cannot have cv-qualifier
error: ‘bool operator<=(const Time&)’ must take exactly two arguments
I'm afraid that I'm at a loss despite having spent the last half-hour googling similar errors.
Thanks!
You have a non-member comparison operator. It makes sense for it to be a non-member rather than a member, but it requires two arguments, and cannot be const:
bool operator <= (const Time& lhs, const Time& rhs) { .... }
Also, you need to fix the logic of the comparison. I am very lazy so I would do it like this:
#include <tuple>
bool operator <= (const Time& lhs, const Time& rhs)
{
return std::tie(lhs.day, lhs.hour) <= std::tie(rhs.day, rhs.hour);
}
See more on operator overloading here.
error: non-member function ‘bool operator<=(const Time&)’ cannot have cv-qualifier
You cannot add const qualifiers to a non member function.
Let me explain you why
The const after a member function guarantees that this function will not change any member variable of this . Now what would a static function guarantee if you don't have any this to refer to?
error: ‘bool operator<=(const Time&)’ must take exactly two arguments
There are 2 ways of overloading operators. You can make them member functions (without the static), but if you want to compare int and Time for example.. Lets write it out:
in your Time class, write out the following operator:
bool operator<=(int rhs) const {return this.minutes <= rhs;}
now, let us compare our data:
Time time;
int integer;
if(time <= integer) {} //This will compile
if(integer <= time) () //This will not compile
lets see why that is:
if(time <= integer) {} //Will expand to this:
if(time.operator<=(integer)) {}
now can you guess what this does?
if(integer <= time) {} //Will expand to this:
if(integer.operator<=(time)) {}
There is no such operator for a default type like integers, and you can't simply just add one to the integer type.
The solution to this are the static operators.
To cover both cases (int <= Time and Time <= int)
you can write this operator as well in your Time class
static bool operator<=(int lhs, const Time& rhs) {};
The parameters are the left side of the comparison and the right side of the comparison.
I also suggest you to take a look at juanchopanza's link:
See more on operator overloading here.
and this link for the difference between member function operators and non member function operators.
If this operator was declared as a class member function then you need to define it the following way
bool Time::operator <= (const Time& other) const{
return (day <= other.day && hour <= other.hour);
}
Also take into account that the condition inside the operator is invalid.
There should be
bool Time::operator <= (const Time& other) const{
return ( day <= other.day ) && ( other.day > day || hour <= other.hour ) );
}
I have a class and i overloaded [ operator to use in main. But the problem here is; somewhere in the class in another function. i want to use [ operator like the old style. How can i use them both or how can i modify my overloaded [ parameter ?
Here is overloading part.
T &operator[](int i)
{
if (i < 0 || i >= ArithmeticVector<T>::size())
throw std::string("Out of bounds!"); //throw std::out_of_range;
else
return data[i];
};
And here is another function i want to use;
friend ArithmeticVector<T> operator /(const ArithmeticVector<T>& v1, const ArithmeticVector<T>& v2 )
{
/*Do quick size check on vectors before proceeding*/
ArithmeticVector<T> result(v1.size());
for (unsigned int i = 0; i < result.size(); ++i)
{
result[i]=v1[i]/v2[i];
}
return result;
};
I get an error like error C2678: binary '[' : no operator found which takes a left-hand operand of type 'const ArithmeticVector'
The problem is with this line.
result[i]=v1[i]/v2[i];
overloaded operator didn't like it :/
I can't understand, what do you mean by I want to use [] operator like the old style, but you should overload operator[] for const version too:
const T& operator[](int i) const
{
// ...
}
v1 and v2 non-modifiable here, they can't call non-const methods.
You need to overload the access operator for const objects as well, because the r.h.s of the expression result[i] = v1[1] / v2 [i] will evaluate to:
v1.operator[](i) / v2.operator[](i)
and both v1 and v2 are of type const ArithmeticVector<T>& which means that the compiler will try to find the operator[](int) const for both of them (they are constant objects). When you overload the operator for const as advised in the answer above, you can re-use the code in the const operator and just call the operator in the non-const operator by casting away constness of the object. That way you don't have to think about what you implemented in one operator and port it to another, and you don't have to debug your code at two places. Here is the model of your problem (I don't have your implementation of ArithmeticVector, so you have to use the parts of it for your stuff):
template<typename T>
class ArithmeticVector;
template<typename T>
ArithmeticVector<T> operator / (
const ArithmeticVector<T>& v1,
const ArithmeticVector<T>& v2
);
template<typename T>
class ArithmeticVector
{
public:
// Your declaration
T& operator[](int i)
{
// Casting away constness allows code re-use.
return const_cast<ArithmeticVector&>(*this).operator[](i);
}
// Const declaration:
T& operator[](int i) const
{
// Put your operator code here.
}
friend ArithmeticVector<T> operator / <> (
const ArithmeticVector<T>& v1,
const ArithmeticVector<T>& v2
);
};
template<typename T>
ArithmeticVector<T> operator / (
const ArithmeticVector<T>& v1,
const ArithmeticVector<T>& v2
)
{
//ArithmeticVector<T> result(v1.size());
ArithmeticVector<T> result;
result[0]=v1[0]/v2[0];
return result;
};
int main(int argc, const char *argv[])
{
ArithmeticVector<int> v1, v2, v3;
v1 = v2 / v3;
return 0;
}
There is a great book of Scott Meyers "Effective C++" and there you can read a great description on constness of objects and access operators. There is an answer on SO, that talks about this.
You need to also take care to avoid a Floating Point Exception (division by zero), or SIGFPE, which will happen when v3[i] == 0, which you can do either by stabilizing the result (you loose accuracy):
result[i] = v1[i] / (v2[I] + 1e-15)
or you introduce a test which slows down the divison significantly (like an if testing if v2[i] == 0).