Suppose we have an operator/ on custom class:
struct my_class {
uint64_t value;
}
template<class T>
constexpr T operator/(const my_class& a, const my_class& b)
{
return static_cast<T>(a.value) / static_cast<T>(b.value);
}
How can one select a / b (where a and b are of my_class type) to return int or double, for example?
You could with a bit of template magic and conversion operators. You can first define a simple wrapper for your expression:
struct DivideMyClass {
DivideMyClass(const MyClass& lhs_, const MyClass& rhs_) : lhs{lhs_}, rhs_{rhs} {}
template<typename T>
operator T () const {
return static_cast<T>(lhs.value) / static_cast<T>(rhs.value);
}
private:
const MyClass& lhs;
const MyClass& rhs;
};
Then, overloading the operator can be done like this:
constexpr DivideMyClass operator/(const my_class& a, const my_class& b)
{
return DivideMyClass{a, b};
}
Then your code will look like this:
double d = MyClass{21} / MyClass{5}; // will be equal to 4.2
Why this solution is bad
The language is not overloading division by the return type. You code will confuse other thinking there's a bug. If you use this method extensively, you will end up in an alomost unreadable code.
Another thing, the conversion is done implicitely, and there's nothing that says if there really was a conversion done in the operator on call site.
You will prevent the AAA idom (Almost Always use Auto). auto may break your code, and it's a bad thing.
Techniques like this should be use for template expression and stuff like that. Using that for simple division will confuse other.
Can I select based on type of variable accepting the result? I.e. int
result = a/b returns int, but double result = a/b returns double?
If you are hell-bent on doing this you can, but it's complicated and I wouldn't recommend it. You have to careful weight the benefits vs the complexity introduced. You can do this via lazy evaluation:
struct X {
int value;
};
struct X_op_proxy {
const X& lhs;
const X& rhs;
template <class T>
operator T() const { return static_cast<T>(lhs.value) / static_cast<T>(rhs.value); }
};
auto operator/(const X& lhs, const X& rhs) -> X_op_proxy
{
return {lhs, rhs};
}
int main()
{
X x1{11}, x2{2};
int i = x1 / x2;
cout << i << endl;
float f = x1 / x2;
cout << f << endl;
}
This is the minimum so you can figure out what this technique is about. You can adapt it and grow it to your needs.
To choose a specific operator template, you must call it as a function:
auto result = operator/<double>(my_class{4}, my_class{2});
// result is 2.0
Related
I was going through code... I found a template class which is declared as shown below.
template <class T>
class tType
{
public:
T value;
T operator=(T val){ value = val; return value; }
tType<T> operator=(tType<T> &val){ value = val.value; return *this; }
operator T(){ return value; }
};
I also found operator overloaded like below...
******1******
template <class T>
bool operator==(T& val, tType<T>& tval) { return(val == tval.value); }
I didn't understand when the above operator gets called... cos when I did...
int main(void)
{
tType<int> x;
x = 5;
if (5 == x)
{
cout << "Both are equal" << endl;
}
return 0;
}
The above said operator was not getting called... and was still working... I also wrote below code for testing and the below code snippet is getting called...
template<class T>
bool operator==(int x, tType<T>& val) { return (x == val.value); }
I wasn't to know who to call *****1*****
It's right that the reason your operator== isn't called is because of the missing const identifier. In this case, the literal 5 is unable to be passed as a variable reference for the paramater T& val. But, that's not quite the whole story.
As you point out, the code still compiles and runs even though the function isn't being called.
The reason your code still works is because of the conversion operator: operator T(){ return value; }.
A conversion operator allows implicit casts from one type to another. For example:
struct Number {
Number(int x) : value(x) { }
operator int() { return value; }
private:
int value;
};
int main() {
Number n(5);
int x = n; // 5 -- operator int() at work
int y = n + x; // 10 -- operator int() at work
Number z = x + y; // 15 -- Number(int) at work
cout << x <<" "<< y <<" "<< z << endl;
return 0;
}
Here, operator int() allows n to convert into an int for assignment to x and to convert to an int for addition with x (the resultant int is then assigned to y), while the unary constructor Number(int) allows the result of x + y to convert back to a Number.
In your code, 5 == x still compiles because the tType<int> x is converted into an int via its operator int() member function, and then that resultant int is compared against the literal 5.
However, this probably isn't a very good design for a class. For example, in order to compare two tType<T>s, a cast into T will be required for one of them.
template <class T>
bool operator==(const T& val, const tType<T>& tval) {
cout << "operator==(const T& val, const tType<T>& tval) was called." << endl;
return(val == tval.value);
}
//...
cout << ( tType<int>() == tType<int>() ) << endl; // calls operator==(const T&, const tType<T>&)
You would rather have an operator== for two tType<T>s.
Another even bigger problem is that this is not symmetric:
cout << (x1 == 5) << endl; // calls operator==(int,int) (the built-in function)
Yikes!
To address all of these, there is a very straightforward design solution. This is taken from Scott Meyers' book Effective C++ Third Edition (a phenomenal book).
Instead of converting back to a T with a conversion operator, the class should include an implicit unary constructor to convert T's up to tType<T>s, and should declare exactly one operator== for tType<T>s:
template <class T>
class tType
{
public:
tType<T>(const T &val) : value(val) { } // unary non-explicit constructor
tType<T> operator=(const tType<T> &val){ value = val.value; return *this; } // only need one
T val() { return value; }
private:
T value; // Note also value is private (encapsulation)
};
template<class T>
bool operator==(const tType<T>& a, const tType<T>& b) { return ( a.val() == b.val() ); }
The important changes:
Added a constructor that takes a single value; this allows converting Ts into tTypes.
Removed the assignment operator taking Ts (because now we can convert them to tTypes.
Only have one equality operator and it takes two const tType<T>&s, meaning operator== can handle any combination of Ts and tType<T>s (or, even better, anything convertible into either of those).
The == operator attempts to bind non-const references to the arguments - values like "5" are not amenable to that... the parameters should be const:
template <class T>
bool operator==(const T& val, const tType<T>& tval) { return val == tval.value; }
As that will still only support e.g. 5 == my_tType and not my_tType == 5, you may want to also provide...
template <class T>
bool operator==(const tType<T>& tval, const T& val) { return val == tval.value; }
...and for my_tType1 == my_tType2...
template <class T>
bool operator==(const tType<T>& tval1, const tType<T>& tval2) {
return tval1.value == tval2.value; }
This gives you maximum control of the comparisons. An alternative is to allow implicit construction of a tType from a T argument, but implicit construction and conversion operators are generally discouraged these days - they can lead to ambiguities and accidental creation of temporaries that can be hard to debug. A topic for another question....
When you say "The above said operator was not getting called... and was still working" - what was actually happening was that tType::operator T() (which returns value;) was being implicitly called, returning an int that could be compared - as an int - to 5. Hence - you had a comparison, but not using the custom operator==. This is a normal result of finding the "best match" for a function call.
Change the function
template <class T>
bool operator==(T& val, tType<T>& tval) { return(val == tval.value); }
to
template <class T>
bool operator==(T const& val, tType<T> const& tval) { return(val == tval.value); }
or
template <class T>
bool operator==(T val, tType<T> tval) { return(val == tval.value); }
Your function was not getting called since 5 cannot be converted to int&.
I have class A
how to overload operator == to perform
A a,b,c;
if (a==b==c) {}
Could anyone help me?
Very short answer: NO!
Slightly longer answer: Don't try this.
Explanation: Every C++ programmer is used to have the comparison operator return a bool or something convertible to bool. Just because it's natural to type things like if (a==b).
So if the expression a==b returns a bool x, then a==b==c would mean comparing x with c. Which makes no sense at all. Even if you get it to compile, e.g. comparing ints that way, it would not yield the result you expect.
So, while there technically I can think of a solution to what you seem to want (compare if all three are equal), the right thing to do is how it is always done in C++: logically chain binary comparisons:
if (a==b && b==c) {}
for the ones who wonder about the "technical doable but oh so ugly" solution:
(DON'T DO THIS IN REAL WORLD USE! You should get fired if you do.)
template <class T>
struct multiCompareProxy {
bool b;
T const& t;
explicit operator bool() const {return b;}
multiCompareProxy operator==(T const& rhs) {
return {b && t.equals(rhs), t};
}
};
template <class T>
multiCompareProxy<T> operator==(T const& lhs, T const& rhs) {
return {lhs.equals(rhs), lhs};
}
A class now just has to overload the euqals method for this to work: Example
If for whatever reason you really wanted to do this, you'd need a proxy object like so:
struct A {};
struct Proxy {};
Proxy operator==(const A& a, const A& b) {
return {};
}
bool operator==(const Proxy& p, const A& b) {
return true;
}
bool operator==(const A& a, const Proxy& p) {
return true;
}
#include <iostream>
int main() {
A a, b, c;
if(a == b == c) {
std::cout << "Bad.\n";
}
}
But don't do this. Use (a == b) && (a == c) like everyone else.
It can be done, and it's very occasionally useful as a kind of domain-specific language (DSL) for matching the notation expected by non-C++-programmers, but it should be studiously avoided for other uses as it'll confound (and annoy) programmers working on the code if this is used willy-nilly.
class A
{
// ...
bool equals(const A& rhs) const { return ... }
struct X
{
X(const A& a, bool b) : a_(a), b_(b) { }
X& operator==(const A& rhs) const { b_ &= a_.equals(rhs); return *this; }
explicit operator bool() const { return b_; }
// remove explicit pre C++11 / consider making it operator void*() ...
const A& a_;
mutable bool b_;
};
X A::operator==(const A& rhs) const
{
return X(*this, equals(rhs));
}
};
(You might prefer standalone functions if you have implicit constructors).
The same kind of proxy-using hackery allows all manner of unexpected notations like 3 < x < 9 and x == a1 || a2 || a3... again, avoid them unless it'll make a huge difference to the maintainers of the code where they'll be used (and ideally that code will have very clear boundaries from the other C++ code in your system).
As an example of good uses of such techniques, consider the boost spirit library and it's unusual use of a lot of operators to provide something approximating BNF notation....
You cannot (minus the possibility of an ugly hack) overload operator==(...) to work as you have specified.
If you think about what it would do a == b would become either true or false (a bool), then you would have (<bool> == c) left. The proper way to do what you are looking to do would be some form of (a==b) && (b==c).
There are times when you can overload an operator to work as you describe, but it would have to return the same type that it takes. An example would be:
class A
{
A& operator+=(A const& rhs)
{
// operator logic
return *this;
}
}
This case works because with a += b += c, you would perform (b += c) which would return an A&, which the remaining a.operator+=(...) accepts as an argument.
bool operator==(T const & a, T const & b) {
return /*boolean expr*/
}
if you have a class you can do:
class MyClass {
public:
bool operator==(T const & rhs) const {
return /*boolean expr*/
}
}
And don't use == twice in a row, you can't, do:
a == b && b == c
I would write:
bool operator==(const A& lhs, const A& rhs){ /* do actual comparison */ }
And use it twice with and operation.
Is it possible to create an overload for the ostream operator that does an arithmetic operation (addition for example) and then streams out the result? The standard ostream overload that can be found all over the web can only stream from a single variable. I need something that does the following:
std::cout << x+y << std::endl;
or even more complex expressions like:
std::cout << x*y+(3*z)^2 << std::endl;
where x, y, and z are instances of a simple custom-made struct where arithmetic operations are already defined (overloaded).
EDIT:
Here is my code:
struct scalar //complex scalar data structure
{
friend scalar operator^(const scalar&, int); //integer power operator overload
friend scalar exp(const scalar&); //exponential power function
std::ostream& operator<<(std::ostream&, const scalar&)
protected:
double re;
double im;
public:
double real() {return re;} //returns the real part
double imag() {return im;} //returns the imaginary part
scalar(double _re, double _im) {re=_re;im=_im;} //constructor 1
scalar(double _re) {re=_re;im=0.0;} //constructor 2
scalar(const scalar& s): re(s.re), im(s.im) {} //copy constructor
scalar& operator=(const scalar& rhs) //assignment operator overload
{
if (&rhs==this) return *this; //checks for self-assignment
re=rhs.re; //sets real parts equal
im=rhs.im; //sets imaginary parts equal
return *this;
}
scalar& operator+=(const scalar& rhs) //compound addition-assignment operator overload
{
if (&rhs==this) return *this; //checks for self-assignment
re=re+rhs.re; //adds real parts
im=im+rhs.im; //adds imaginary parts
return *this;
}
scalar& operator*=(const scalar& rhs) //compound multiplication-assignment operator overload
{
if (&rhs==this) return *this; //checks for self-assignment
double x1=re; double x2=rhs.re; double y1=im; double y2=rhs.im;
re=x1*x2-y1*y2; //multiplies real parts
im=x1*y2+x2*y1; //multiplies imaginary parts
return *this;
}
scalar& operator-=(const scalar& rhs) //compound subtraction-assignment operator overload
{
if (&rhs==this) return *this; //checks for self-assignment
re=re-rhs.re; //adds real parts
im=im-rhs.im; //adds imaginary parts
return *this;
}
scalar& operator/=(const scalar& rhs) //compound division-assignment operator overload
{
if (&rhs==this) return *this; //checks for self-assignment
double x1=re; double x2=rhs.re; double y1=im; double y2=rhs.im;
double n;
n =pow(x2,2)+pow(y2,2);
if (n==0) throw(1);
re=(x1*x2+y1*y2)/n; //multiplies real parts
im=(x2*y1-x1*y2)/n; //multiplies imaginary parts
return *this;
}
const scalar operator+(const scalar& b) //addition operator overload
{
scalar c = *this;
c+=b;
return c;
}
const scalar operator*(const scalar& b) //addition operator overload
{
scalar c = *this;
c*=b;
return c;
}
const scalar operator-(const scalar& b) //addition operator overload
{
scalar c = *this;
c-=b;
return c;
}
const scalar operator/(const scalar& b) //addition operator overload
{
scalar c = *this;
c/=b;
return c;
}
};
scalar i(0.0,1.0);
scalar j(0.0,1.0);
std::ostream& operator<<(std::ostream& out, const scalar& s)
{
out << s.re << '+' << s.im << 'i';
return out;
}
scalar operator^(scalar a, int b) //integer power operator overload
{
double x=a.real(); double y=a.imag();
if (x==0) throw(1);
int r=sqrt(pow(x,2)+pow(y,2));
int arg=atan2(y,x);
scalar c(r*cos(arg),r*sin(arg));
return c;
}
scalar exp(const scalar& s) //exponential power function
{
double x=s.re; double y=s.im;
scalar c(exp(x)*cos(y),exp(x)*sin(y));
return c;
}
Here is my main function:
int main()
{
scalar x(3,4);
scalar y=2;
cout << x*y << endl;
return 0;
}
This is is the output it is supposed to give:
6+8i
And this is the errors it gives instead:
In function 'std::ostream& operator<<(std::ostream&, const scalar&)':|
error: passing 'const scalar' as 'this' argument of 'double scalar::real()'
discards qualifiers|
And if I remove the const as the compiler says, I will get the following error:
error: no match for 'operator<<' in 'std::cout << scalar::operator*(const scalar&)
(((const scalar&)((const scalar*)(& y))))'|
The << operator can't handle the full expression - and why should it?
You need to implement the separate operators (operator+, operator*, ...) for your struct, which take your structs as parameters, do the corresponding operation on it, and return another of your structs. And only then define a operator<< taking a single one of your structs.
How would you even think of passing in such a complex structure to the operator<<, let alone parse it in there? Implement the separate operators, and leave the parsing to the compiler.
e.g. for a simple struct only encapsulating an int, doing that with + operation would look like this:
struct mystruct
{
int value;
};
then define:
mystruct const operator+(mystruct const & a, mystruct const & b)
{
mystruct result;
result.value = a.value + b.value;
return result;
}
and
std::ostream & operator<<(std::ostream& out, mystruct const & a)
{
out << a.value;
return out;
}
then you can do:
mystruct a, b;
a.value = 1;
b.value = 2;
std::cout << a+b;
Edit: With your updated code, there's exactly one problem:
std::ostream& operator<<(std::ostream&, const scalar&)
should be
friend std::ostream& operator<<(std::ostream&, const scalar&);
i.e. you're missing friend and an ;
Though the error you show suggests some different problem (which jrok's answer would have a solution for) - that doesn't seem to result from compiling the code you show! So please get the shown code and error message in sync.
The error is because functions scalar::real and scalar::imag are not const - you can only call const member functions when you've got a reference to a constant scalar.
double real() const {return re;}
double imag() const {return im;}
Why don't you just write std::cout << (x+y) << std::endl;
and be done?
As long as your overloaded operator takes its argument by value:
ostream& operator<<(ostream&, Thing)
or constant reference:
ostream& operator<<(ostream&, const Thing&)
you can use it for any expression with type Thing.
You should put parentheses around complex expressions, to avoid surprises from operator precedence; in particular, the second expression involving ^ won't be parsed as you expect.
You'll only be restricted to a single variable (or, more accurately, an lvalue expression) if the operator requires a non-constant reference; so don't do that.
UPDATE Now we've seen the code, the main issue is the in-class definition of operator<< as a member function; it can't be a member. Perhaps you want it to be a friend, so it can access im and re; or perhaps you should remove the declaration (making it a non-member, non-friend), and just use the public interface. If you do that, you'll need to add const to real() and imag(), so they can be called on a const object. You should do that anyway.
(Looking at the reported error, it seems you've already changed it to use the public interface, but haven't declared the necessary functions const).
How can I define operator ** such that it can perform exponentiation of 2 numbers . eg 2 ** 3. It should give answer as 8.
Or Indirectly is there any way I can do this with operator overloading instead of #define macros ?
You can't. You can only overload existing operators, and not for built in types.
You can't. You can only overload existing operators in C++; you cannot add new ones, or change the arity or associativity of existing operators. Even the preprocessor is powerless here - its identifiers cannot be symbols.
If you're willing to make a compromise w.r.t. ** and feel like obfuscating your code:
#include <cmath>
#include <iostream>
struct foo {
foo(int i) : i_(i) {}
int operator*(int exp)
{
return std::pow(i_,exp);
}
private:
int i_;
};
struct bar {
} power_of;
foo operator*(int i, bar)
{
return foo{i};
}
int main()
{
std::cout << 2 *power_of* 3; // prints 8
}
Otherwise, just use std::pow.
Like the other answers noted, this isn't possible for built-in types BUT you can get this to work for custom types like so (minimum code sample):
#include <cmath>
#include <iostream>
struct dummy;
struct Int
{
int i;
Int() : i(0) {}
Int(const int& i) : i(i) {}
dummy operator*();
};
struct dummy
{
Int* p;
dummy(Int* const p) : p(p) {}
int& operator*()
{
return p->i;
}
};
dummy Int::operator*()
{
return dummy(this);
}
int operator*(const Int& lhs, const dummy& rhs)
{
return std::pow(lhs.i, rhs.p->i);
}
int main()
{
Int a(2);
Int b(2);
std::cout<< a ** b << std::endl;
}
Live example
As others have noted: that isn't possible. You can overload another operator, like ^, for exponentiation, instead however on a simple type wrapper class/object.
But, if you're adventurous, another way, is to create a micro DSL that supports on-the-fly calculation of such an operator. (A famous example of that is LISP in C++)
However, given the effort involved, it may or may not be your cup of tea. However, it's worth knowing that such a possibility exists.
UPDATE:
Operator-Overloading works by overloading already existing operators. Why? Because if you could define your own, you will also have to define the precedence of such operators which can easily give way to abusing operators by abstracting away their original purpose - which increases difficulty when reading code. (At least that's the argument that's been made).
The closest operator that has a semantic meaning close to ** is the caret operator. A naive and illustrative implementation of such an operator is:
#include <iostream>
#include <cmath>
class Int {
public:
Int() {}
Int(int i) : value(i) {}
friend double operator^(const int& i, const Int& integer);
friend double operator^(const Int& integer, const int& i);
friend double operator^(const Int& lhs, const Int& rhs);
private:
int value;
};
double operator^ (const int& lhs, const Int& rhs) {
return std::pow(lhs, rhs.value);
}
double operator^ (const Int& lhs, const int& rhs) {
return std::pow(lhs.value, rhs);
}
double operator^ (const Int& lhs, const Int& rhs) {
return std::pow(lhs.value, rhs.value);
}
int main() {
Int i1 = 10;
Int i2 = 3;
double result = i1 ^ i2;
std::cout << result;
return 0;
}
Unfortunately the set of operators that can be overloaded in C++ is fixed and does not include the ** operator. You might think of using operator^() instead, but it turns out that ^ has the wrong precedence to serve as an exponentiation operator.
In short, there's not much you can do about this, unfortunately.
You can't overload operators for built-in types. I'd use operator ^ for such purpose for custom types.
Whats wrong with my code shown below? please somebody throw some light. Thanks for your time !
#include<iostream.h>
using namespace std;
struct mydata{
int mx;
mydata(int x = 0){}
mydata operator+(const mydata& rhs){
mydata temp(rhs);
return temp;
}
operator int() const{ return mx; }
operator double() const{ return mx; }
};
int main(){
mydata d;
mydata r = d + 5; // L1
5 + d; // L2
d + d; // L3
}
First, you haven't stated what the problem is, but presumably you want an operator+ that sums the mx values of two mydata objects:
mydata operator+(const mydata& rhs){
return mydata (mx + rhs.mx);
}
Next, I would suggest making this a non-member function, so that the LHS and RHS get treated in the same way, fixing the problem in L2:
mydata operator+(const mydata& lhs, const mydata& rhs){
return mydata (lhs.mx + rhs.mx);
}
Finally, you will have an ambiguous overload remaining, because the compiler cannot decide whether to use the built-in operator+(int,int) or your own operator+(const mydata&, const mydata&). You can fix this by removing the cast operators int() and double().
See demo here.
The problem (stated the comment) is that compiler doesn't know which + you want to execute:
(double)d + 5
or
(int)d + 5
In order to resolve this ambiguoity, you should point the type conversion, or replace one of these operators by a named function:
operator int() const{ return mx; }
operator double() const{ return mx; }
If you want instead use d + mydata(5) you should write so, because the above variants are more likely to be applied
You could provide a few non-member operator+ to enable operator+ with different data type:
mydata operator+(const mydata& lhs, const mydata& rhs){
return mydata (lhs.mx + rhs.mx);
}
mydata operator+(int mx, const mydata& rhs){
return mydata (rhs.mx+mx);
}
mydata operator+(const mydata& lhs, int mx){
return mydata(lhs.mx+mx);
}
You can't do 5 + d. 5 can not be converted to class object like this. For this you need to get the operator + definition out of the class method. (in my knowledge preferably friend).