C++ overloading of the plus operator - c++

I want to add 2 objects, by overloading the + operator, but my compiler says there's no matching function to call to point::point(int, int). Can somebody please help me with this code, and explain the error ? thank you
#include <iostream>
using namespace std;
class point{
int x,y;
public:
point operator+ (point & first, point & second)
{
return point (first.x + second.x,first.y + second.y);
}
};
int main()
{
point lf (1,3)
point ls (4,5)
point el = lf + ls;
return 0;
}

You can just change your code like this,
#include <iostream>
using namespace std;
class point {
int x, y;
public:
point(int i, int j)
{
x = i;
y = j;
}
point operator+ (const point & first) const
{
return point(x + first.x, y + first.y);
}
};
int main()
{
point lf(1, 3);
point ls(4, 5);
point el = lf + ls;
return 0;
}
Hope this helps...

class point{
int x,y;
public:
point& operator+=(point const& rhs)& {
x+=rhs.x;
y+=rhs.y;
return *this;
}
friend point operator+(point lhs, point const& rhs){
lhs+=rhs;
return lhs;
}
};
There are a pile of little tricks above that make following this pattern a good "no brainer".
You get both += and + with the "proper" semantics.
If you chain +s together, you get elision of the left hand side operation. (ie, a+b+c becomes (a+b)+c, the return value of a+b is elided into the _+c call). If your objects have movable state, the proper moves happen for no design cost.
a+b works if either a or b is a point, and the other has an implicit-conversion-to-point. Member operator+ does not do this if a is not a point; this is pointless asymmetry.
a+=b is often more efficient to implement than a=a+b. When you implement += here, you get an efficient + as well. And your += is in turn defined in terms of member variable +=s.

The error with gdb I get is
main.cpp:8:49: error: ‘point point::operator+(point&, point&)’ must take either zero or one argument
This is because the the object that you plan to perform the operation on is this (the left hand side) and then the right hand side is the argument. If you wish to use the format that you've taken, then you can put the declaration outside the class - ie
struct point
{
// note made into a struct to ensure that the below operator can access the variables.
// alternatively one could make the function a friend if that's your preference
int x,y;
};
point operator+ (const point & first, const point & second) {
// note these {} are c++11 onwards. if you don't use c++11 then
// feel free to provide your own constructor.
return point {first.x + second.x,first.y + second.y};
}

Related

C++ Can I overload the bracket [] operator to do different things if it on the LHS vs RHS of an assignment?

I am looking to accomplish the following:
int x, y, z;
foo[x] = y; acts like do_this(x,y);
z = foo[x]; acts like z = do_that(x)
I can accomplish the first with a Foo class and a Helper class, where the operator[] returns by value a Helper class constructed with x, and the operator= for the Helper class is defined to run do_this(this->x, y). Like below:
class Foo {
public:
Helper operator[](int x) {
return Helper(x);
}
};
class Helper {
public:
Helper(x) {
this->x = x;
}
void operator=(int y) {
do_this(this->x, y);
}
private:
int x;
};
What I can't figure out is how to accomplish (2). Is there a way to overload the operator[] so that it knows if it was used on the lhs vs the rhs?
Yes - give your Helper class a conversion function to int:
class Helper {
public:
Helper(x){
this->x = x;
}
Helper& operator= (int y) {
do_this(this->x, y);
return *this;
}
operator int() const {
return do_that(this->x);
}
private:
int x;
};
This will also allow other uses like product *= foo[x]; or func_taking_int(foo[x]), etc.
One potential catch is that some uses of auto or function templates would still just keep the type Helper, which might not be what's wanted - so users of Foo should still understand that this proxy sugar is going on. It could also be helpful to have some alternative syntax to explicitly get the int value for cases like that, in either Foo or Helper.
I'm not sure I've understood what you actually want to do, but you are might be able to use the const version of the operator[] vs. the non-const version. For example:
struct Foo {
Z operator [] (int x) const { // this last const is important
return do_that(x);
}
Helper operator [] (int x) {
// as you yourself have written.
}
};
There are more tips and tricks to this, for forwarding arguments perfectly (a.k.a "perfect forwarding",) for being "const correct", and many other small things, but the gist of it is the above.

C++ should I use pointer or reference?

I would like to have an insight about whenever I should be using references or pointers.
Let's take the example of a Polygon class using a Rectangle class for its internal bounding box.
Polygon.h
class Polygon {
private:
std::list<Point> _points;
Rectangle _boundingBox;
public:
Polygon(const std::list<Point> &);
public:
const std::list<Point> &getPoints() const;
const Rectangle &getBoundingBox() const;
private:
void setBoundingBox();
};
Polygon.cpp
#include <iostream>
#include "Polygon.h"
Polygon::Polygon(const std::list<Point> &points)
{
if (points.size() < polygon::MIN_SIDE + 1) {
throw std::invalid_argument("A polygon is composed of at least 3 sides.");
}
if (points.front() != points.back()) {
throw std::invalid_argument("A polygon must be closed therefore the first point must be equal to the last one.");
}
std::list<Point>::const_iterator it;
for (it = ++points.begin(); it != points.end(); ++it) {
this->_points.push_back(*it);
}
this->setBoundingBox();
}
void Polygon::translate(const std::array<float, 2> &vector)
{
std::list<Point>::iterator it;
for (it = this->_points.begin(); it != this->_points.end(); ++it) {
(*it).setX((*it).getX() + vector[0]);
(*it).setY((*it).getY() + vector[1]);
}
Point topLeft = this->_boundingBox->getTopLeft();
Point bottomRight = this->_boundingBox->getBottomRight();
topLeft.setX(topLeft.getX() + vector[0]);
topLeft.setY(topLeft.getY() + vector[1]);
bottomRight.setX(bottomRight.getX() + vector[0]);
bottomRight.setY(bottomRight.getY() + vector[1]);
}
const std::list<Point> &Polygon::getPoints() const
{
return this->_points;
}
const Rectangle &Polygon::getBoundingBox() const
{
return this->_boundingBox;
}
void Polygon::setBoundingBox()
{
float xMin = this->_points.front().getX();
float xMax = this->_points.front().getX();
float yMin = this->_points.front().getY();
float yMax = this->_points.front().getY();
std::list<Point>::const_iterator it;
for (it = this->_points.begin(); it != this->_points.end(); ++it)
{
Point point = *it;
if (point.getX() < xMin) {
xMin = point.getX();
}
if (point.getX() > xMax) {
xMax = point.getX();
}
if (point.getY() < yMin) {
yMin = point.getY();
}
if (point.getY() > yMax) {
yMax = point.getY();
}
}
this->_boundingBox = new Rectangle(Point(xMin, yMin), Point(xMax, yMax));
}
std::ostream &operator<<(std::ostream &out, const Polygon &polygon)
{
std::list<Point>::const_iterator it;
for (it = polygon.getPoints().begin(); it != polygon.getPoints().end(); ++it) {
out << (*it);
if (it != polygon.getPoints().end()) {
out << " ";
}
}
return out;
}
Rectangle.h
#pragma once
#include <stdexcept>
#include "Point.h"
class Rectangle {
private:
Point _topLeft;
Point _bottomRight;
public:
Rectangle(const Point &, const Point &);
public:
const Point &getTopLeft() const;
const Point &getBottomRight() const;
float getWidth() const;
float getHeight() const;
};
Rectangle.cpp
#include "Rectangle.h"
Rectangle::Rectangle(const Point &topLeft, const Point &bottomRight)
{
if (topLeft.getX() > bottomRight.getX() || topLeft.getY() > bottomRight.getY()) {
throw std::invalid_argument("You must specify valid top-left/bottom-right points");
}
this->_topLeft = topLeft;
this->_bottomRight = bottomRight;
}
const Point &Rectangle::getTopLeft() const
{
return this->_topLeft;
}
const Point &Rectangle::getBottomRight() const
{
return this->_bottomRight;
}
float Rectangle::getWidth() const
{
return this->_bottomRight.getX() - this->_topLeft.getX();
}
float Rectangle::getHeight() const
{
return this->_bottomRight.getY() - this->_topLeft.getY();
}
Point.h
#pragma once
#include <ostream>
#include <cmath>
class Point {
private:
float _x;
float _y;
public:
Point(float = 0, float = 0);
public:
float distance(const Point &);
public:
float getX() const;
float getY() const;
void setX(float);
void setY(float);
};
std::ostream &operator<<(std::ostream &, const Point &);
bool operator==(const Point &, const Point &);
bool operator!=(const Point &, const Point &);
Point.cpp
#include "Point.h"
Point::Point(float x, float y)
{
this->_x = x;
this->_y = y;
}
float Point::distance(const Point &other)
{
return std::sqrt(std::pow(this->_x - other.getX(), 2) + std::pow(this->_y - other.getY(), 2));
}
float Point::getX() const
{
return this->_x;
}
float Point::getY() const
{
return this->_y;
}
void Point::setX(float x)
{
this->_x = x;
}
void Point::setY(float y)
{
this->_y = y;
}
std::ostream &operator<<(std::ostream &out, const Point &point)
{
out << "(" << point.getX() << ", " << point.getY() << ")";
return out;
}
bool operator==(const Point &p1, const Point &p2)
{
return p1.getX() == p2.getX() && p1.getY() == p2.getY();
}
bool operator!=(const Point &p1, const Point &p2)
{
return p1.getX() != p2.getX() || p1.getY() != p2.getY();
}
A lot of questions come with this snippet of code.
This does not compile because obviously whenever we try to create a Polygon, it ends up trying to create a Rectangle with a default constructor which does not exist.
I can't use initializer list because obviously the bounding box depends on some computed values from my list of points.
I could create a default constructor creating two Point(0, 0) by default for the Rectangle but this does not make much sense.
I could use pointers but then I feel this is not the nicest solution as I tend to think this is mostly used for polymorphism in C++ we should prefer reference whenever possible.
How should I then proceed ?
I feel I am missing something out about C++ and could learn a lot from this.
I think your main question is about how to deal with the problem of needing to initialize both std::list<Point> _points; and Rectangle _boundingBox;, while also doing some validation of _points.
The simplest solution is to just give Rectangle a default constructor (or pass two default Points as initializer). Then once you have validated the points argument in the constructor, you calculate the Rectangle based on the points.
A slightly more complicated alternative is to allow the validation function to be invoked from the ctor-initializer list, e.g.:
Polygon::Polygon(std::list<Point> points)
: _points( validate_point_list(points), std::move(points) ), _boundingBox( calculateBoundingBox(_points) )
{
}
where you have functions (which could be free functions):
void validate_point_list(std::list<Point> &points)
{
if (points.size() < polygon::MIN_SIDE + 1)
throw std::invalid_argument("A polygon is composed of at least 3 sides.");
if (points.front() != points.back())
throw std::invalid_argument("A polygon must be closed therefore the first point must be equal to the last one.");
// caller must pass in same first and last point, but we only store one of the two
points.erase( points.begin() );
}
and
Rectangle calculateBoundingBox(std::list<Point> const &_points)
{
// whatever logic you have in setBoundingBox, except return the answer
}
Note that the loop in your Polygon constructor is unnecessarily complicated. You could have just written _points = points; and then erased the extra point (which is O(1) for lists).
Note that I have passed by value and then used std::move. The reason is that if the argument given is a rvalue then it can just be moved right on through into where it's being stored; whereas with the const & version, a copy is stored and then the original is destructed.
I would use const & a lot less than you did. Small objects , such as Point and Rectangle, don't suffer a performance penalty from pass-by-value (and might even be more efficient that way). And as mentioned in the previous paragraph; if your function accepts a parameter and it is going to take a copy of that parameter, it's better to pass by value .
Passing by reference is best only when you are using but not storing the values passed. For example, calculateBoundingBox.
Finally, once you get this working, you might want to think about having the Polygon constructor accept an iterator pair of points range, and/or a std::initializer_list.
I would defined a default constructor for Rectangle class as private and I would make Polygon class a friend of Rectangle class:
class Rectangle {
friend class Polygon;
Point _topLeft;
Point _bottomRight;
Rectangle(); // accessible only to friends
public:
Rectangle(Point const&, Point const&);
...
};
And then in setBoundingBox():
void Polygon::setBoundingBox() {
...
_boundingBox._topLeft = Point(xMin, yMin);
_boundingBox._bottomRight = Point(xMax, yMax);
}
Thus, I wouldn't expose the default constructor of Rectangle and at the same time I would have a concrete object which is more efficient in terms of cache performance.
I feel as though you should have a separate class called BoundingBox that
1) Takes a collection of points in its constructor
2) Is inherited from Rectangle
Meanwhile, Rectangle should have a state, along the lines of NOT_A_RECTANGLE or it could throw an exception. Just be sure you clean up when throwing exceptions from a constructor.
Then you would construct the bounding box as part of the construction of the polygon and you can verify that a bounding box is possible as part of your error checking. (probably rather than 3 sides check, but I am no geometry expert)
BoundingBox would remain a member of Polygon.
This would be more RTTI.
It occurs to me though, that if you translate or rotate the polygon, you've also go to translate or rotate the bounding box. You might want to consider making the list of points its own object and sharing them. This would be a more advanced topic. You can for now get away with just recalculating the bounding box on operations performed upon the polygon.
As to whether to use a reference, a pointer, or pass by value, I don't know that there is a black and white list of things to consider for this, but a few are:
Is the object large enough to even worry about it? A rectangle is 4 floats?
Are there interfaces or base classes you will need to cast to, rather than always using the class itself? If so, you've got no choice but to use a pointer of some sort. The pointer could be unique, shared, weak, etc. depending on the situation. You have to ask yourself who owns it, whats the life time, and are there circular references?
Most people will probably use a reference whenever possible rather than a pointer, but only when passing by value doesn't qualify.
IMO, since you are just "GetBoundingBox", I think it would be simple and more maintainable to just return a copy of the bounding box by value rather than some const reference and definitely more than a pointer.
One solution would be to write a programmatic constructor for Rectangle that takes as its argument a const std::list<Point>&. It could traverse the list once, computing the maximum and minimum x and y. Then, your Polygon constructor would become:
Polygon::Polygon(const std::list<Point> &points)
: _points(points),
: _boundingBox(points)
{
// ...
}
An alternative is to move the code to find the bounding box from a list of points to a helper function, then define a move constructor Rectangle::Rectangle( Rectangle&& x ). In that case, your Polygon constructor would be:
Polygon::Polygon(const std::list<Point> &points)
: _points(points),
: _boundingBox( findBoundingBox(points) )
{
// ...
}
Either way, you could update a bounding box with assignment, so you might want an assignment operator like Rectangle& Rectangle::operator= ( Rectangle&& x ) to make that more efficient. You can skip the Rectangle&& versions if a Rectangle is just Plain Old Data. But if you do this a lot, you might overload Rectangle& findBoundingBox( const std::list<Point>& src, Rectangle& dest ) to update in place with no copying.
On a minor side note, I’d discourage you from using identifiers that begin with underscores, since those names are reserved in the global namespace in C++, and your libraries might declare something named _point.

Overloading operator+ in c++

I have a little problem with one of my task for exercise for exam. This is a text:
Class MyFloat have a private variable float num. You have to write methods which will enable next lines of code:
MyFloat x = 3.5;
MyFloat y = x + 3.2
float z = 3.4 + y
And I write this code:
#include <iostream>
#include <Windows.h>
using namespace std;
class MyFloat
{
float num;
public:
MyFloat(float n)
{
num = n;
}
MyFloat operator+(MyFloat x)
{
float result;
result = x.num + this->num;
return result;
}
};
int main()
{
MyFloat x = 3.75;
MyFloat y = x + 3.2;
float z = 3.4 + y;
system("PAUSE");
}
I get error in this line:
float z = 3.4 + y;
It says:
error C2677: binary '+' : no global operator found which takes type 'MyFloat' (or there is no acceptable conversion)
What should I do? How to solve this problem???
Implement operator+ as non-member friend function with 2 arguments MyFloat operator+(MyFloat x, MyFloat y).
Why doesn't it work in the current version? Because member operator functions are called on the objects on the left side of the operator. In your case on the left side you have integer literal which is not an object so lacks MyFloat operator+(MyFloat x) member function.
Non-member variants of operators are symmetrical and do not require the left side being an object. Symmetricity is important because as you see in your example operator+ is not symmetrical as we are used to think in math
Edit: But this is still not enough as noted by Cassio Neri in comments. Why? See his answer for the explanation but in short: you have ambiguity problems. You can use either his solution or this one if you do manual casting like this: float z = 3.4f + static_cast<float>(y); which is quite ugly. You can use another cast: float z = MyFloat(3.4f) + y if you provide MyFloat::operator float conversion.
Another solution to solve the same ambiguity problem: In C++11 you could use your own suffix literal (similar to f prefix for built-in floats, for example 3.4_f; (underscore means that this suffix literal is user-defined). Sample implementation (given that you implement operators for casting from MyFloat to float and backwards:
MyFloat operator "" _f(long double val) {
return MyFloat(static_cast<float>(val)); }
int main() {
MyFloat x = 3.75;
MyFloat y = x + 3.2;
float z = 3.4_f + y;
}
This can be a solution:
class MyFloat
{
float num;
public:
MyFloat(float n)
{
num = n;
}
operator float() const {
return num;
}
};
int main()
{
MyFloat x = 3.75;
MyFloat y = x + 3.2f;
float z = 3.4f + y;
}
Initially, I also though about making MyFloat operator+(MyFloat, MyFloat) a non-member friend function but it still doesn't make the line
float z = 3.4 + y;
to compile. The reason is that 3.4 + y will be of type MyFloat and therefore you can't assign it to float z unless you provide a converting operator from MyFloat to float. Buth then, 3.4f + y becomes ambiguous (at least for VS 2010) because it can either call MyFloat operator+(MyFloat, MyFloat) or it can convert y to float and use the built-in operator + for floats.
You only have MyFloat + float operation, and you need to define float + MyFloat operation too. They are not the same.
Add this to your public functions:
friend float operator+ (const float& lhs, const MyFloat& rhs);
And this outside the class:
float operator+ (const float& lhs, const MyFloat& rhs) {
return lhs + rhs.num;
}
Note: Edited as per comment by CassioNeri.
While you can proceed with the answer where you define the "cast to float" approach, I believe it is better for your own sake that you start making use of your public API to implement additional behavior.
In general, a simple "casting" will not do the trick (for example, what happens if MyFloat were MyMatrix?).
The approach below is certainly more verbose, but it stresses that you should "eat your own food", meaning that you should try to implement additional behavior based on your own public interface, rather than a bunch of obscure implicit casts, or friend functions. If you use your own API: You will understand its limitations, and may potentially save recompilation of the main class if you make modifications.
Also, suppose that you wanted to count the accesses to your class (or otherwise control access to the underlying value): using the casting operator you would need to duplicate the code in operator float() and in float value().
So, here is my humble suggestion which appears longer but, to my taste, better reflects OO design principles.
#include<iostream>
class MyFloat {
public:
MyFloat(float value):
m_value(value) { }
float value() const {
return m_value;
}
private:
float m_value;
};
// Eat your own food: implement functions using your public interface
// until proven need to do otherwise. This will help you assess the
// usability of your API.
float operator+(const MyFloat& lhs, const MyFloat& rhs) { return lhs.value() + rhs.value(); }
float operator+(const MyFloat& lhs, float rhs) { return lhs.value() + rhs; }
float operator+(float lhs, const MyFloat& rhs) { return lhs + rhs.value(); }
// See, now I can define another operator without need to recompile my
// class (this could have been placed in another file)
std::ostream& operator<<(std::ostream& os, const MyFloat& mf) {
os<<"MyFloat("<<mf.value()<<")";
return os;
}
int main() {
MyFloat x = 3.5; // would not work if I had declared the constructor as "explicit"
MyFloat y = x + 3.2;
MyFloat z = 3.4 + y;
std::cout<<x<<", "<<y<<", "<<z<<std::endl;
}
Output (compiled with g++ example.cpp -Wall -Wextra):
MyFloat(3.5), MyFloat(6.7), MyFloat(10.1)

Constructing result in operator vs operating on default-constructed object

I have a class which is essentially an array with labelled contents, and I'd like to define some operators for it. I'd like to do it in such a way that changing the number of elements in the class is easy, as I expect future users will change the variables tracked, but I'd also like to ensure that basic arithmetic operations on the class are as efficient as possible.
I can see two way of implementing the operators. Taking the example of a Vector2D class:
struct Vector2D {
//members
const static int nElem = 2;
double x;
double y;
//Constructors
Vector2D() {}
Vector2D(double X, double Y) : x(X), y(Y) {}
//Operators
double& operator[] (int index) {
switch(index) {
case 0:
return x;
case 1:
return y;
default:
return std::out_of_range ("Oops");
}
}
// Option 1: operator+ by constructing result
Vector2D operator+ (const Vector2D & rhs) const {
return Vector2D(x + rhs.x, y+rhs.y);
}
// Option 2: operator+ using loop and [] operator
Vector2D operator+ (const Vector2D & rhs) const {
Vector2D result;
for(int i = 0; i < nElem; i++)
result[i] = (*this)[i] + rhs[i];
return result;
}
};
Assuming I use -03 optimization, will there be any difference between the two implementations of operator+? My understanding is that since the default Vector2D constructor has no code body and the class contents are a default data type, there is no extra overhead in Option 2 for calling the default constructor on result before setting its members. I expect the two to be equivalent, but I'm not confident enough in my knowledge to be sure.
Your method won't work at all. If you want someone to be able to change nElem you can't use x, y as your names. Why? Because changing nElem to 3 won't magically add z. And since you can't do a for loop over x and y, your definition of nElem is meaningless.
Finally, this is a textbook case for the use of a number template. Create a vector which is templated over how many elements it has.
Do something like this:
template<unsigned int LEN>
class Vector{
double v[LEN];
public:
Vector operator+(const Vector &o){
Vector res;
for (unsigned int i=0;i<LEN;++i) // with -O3 and small LEN this will be unrolled
res.v[i]=v[i]+o.v[i];
}
// ... etc.
};
Then you use it like this:
Vector<2> my_2d_vec;
Vector<3> my_3d_vec;

Can we declare a function with the same signature but different return type in the base class?

the question may look silly ,but i want to ask..
Is there any way we can declare a method in a class with same signature but different return type (like int fun(int) and float fun(int) ) and during the object creation can we dynamically decide which function to be executed! i have got the compilation error...is there any other way to achieve this logic may be using templates...
You can always take the return value as a template.
template<typename T> T fun(int);
template<> float fun<float>(int);
template<> int fun<int>(int);
Can you decide dynamically at run-time which to call? No.
#DeadMG proposed the template based solution, however you can simply "tweak" the signature (which is, arguably, what the template argument does).
The idea is simply to add a dummy argument:
struct Foo
{
float fun(float); // no name, it's a dummy
int fun(int); // no name, it's a dummy
};
Then for execution:
int main() {
Foo foo;
std::cout << foo.fun(int()) << ", " << foo.fun(float());
}
This can be used exactly as the template solution (ie invoked from a template method), but is much easier to pull:
less wordy
function template specialization should be defined outside the class (although VC++ will accept inline definition in the class)
I prefer to avoid function template specialization, in general, as with specialization on arguments, the rules for selecting the right overload/specialization are tricky.
You can (but shouldn't*) use a proxy class that overloads the conversion operators.
Long example with actual usecase *
Let me take my example from Dot & Cross Product Notation:
[...]
There is also the possibility of having operator* for both dot-product and cross-product.
Assume a basic vector-type (just for demonstration):
struct Vector {
float x,y,z;
Vector() {}
Vector (float x, float y, float z) : x(x), y(y), z(z) {}
};
We observe that the dot-product is a scalar, the cross-product is a vector. In C++, we may overload conversion operators:
struct VecMulRet {
public:
operator Vector () const {
return Vector (
lhs.y*rhs.z - lhs.z*rhs.y,
lhs.z*rhs.x - lhs.x*rhs.z,
lhs.x*rhs.y - lhs.y*rhs.x
);
}
operator float () const {
return lhs.x*rhs.x + lhs.y*rhs.y + lhs.z*rhs.z;
}
private:
// make construction private and only allow operator* to create an instance
Vector const lhs, rhs;
VecMulRet (Vector const &lhs, Vector const &rhs)
: lhs(lhs), rhs(rhs)
{}
friend VecMulRet operator * (Vector const &lhs, Vector const &rhs);
};
Only operator* is allowed to use struct VecMulRet, copying of VecMulRet is forbidden (paranoia first).
Operator* is now defined as follows:
VecMulRet operator * (Vector const &lhs, Vector const &rhs) {
return VecMulRet (lhs, rhs);
}
Et voila, we can write:
int main () {
Vector a,b;
float dot = a*b;
Vector cross = a*b;
}
Btw, this is blessed by the Holy Standard as established in 1999.
If you read further in that thread, you'll find a benchmark that confirms that this comes at no performance penalty.
Short example for demonstration *
If that was too much to grasp, a more constructed example:
struct my_multi_ret {
operator unsigned int() const { return 0xdeadbeef; }
operator float() const { return 42.f; }
};
my_multi_ret multi () {
return my_multi_ret();
}
#include <iostream>
#include <iomanip>
int main () {
unsigned int i = multi();
float f = multi();
std::cout << std::hex << i << ", " << f << std::endl;
}
* You can, but shouldn't, because it does not conform to the principle of least surprise as it is not common practice. Still, it is funny.