What do I often see references in operator overloading definitions? - c++

For example, in the OGRE3D engine, I often see things like
class_name class_name :: operator + (class_name & object)
Instead of
class_name class_name :: operator + (class_name object)
Well it's not that I prefer the second form, but is there a particular reason to use a reference in the input ? Does it has special cases where it is necessary to use a reference instead of a copy-by-value ? Or is a performance matter ?

It's a performance issue. Passing by reference will generally be cheaper than passing by value (it's basically equivalent to passing by pointer).
On an unrelated note, you probably want the argument to operator+ to be const class_name &object.

It is recommended to implement operator+ in terms of operator+=. First make a copy of the left argument, then modify it, and finally return the copy. Since you are going to copy the left argument anyway, you might just as well do it by using call by value for the left argument:
class_name operator+(class_name x, const class_name& y)
{
return x += y;
}
In C++0x, you should enable move semantics for the result:
#include <utility>
class_name operator+(class_name x, const class_name& y)
{
return std::move(x += y);
}

Besides the "usual" calling conventions for regular methods, I would note that the operators are somewhat peculiar.
The main reason to use const& instead of pass-by-value is correctness (performance comes second, at least in my mind). If your value may be polymorphic, then a copy means object slicing, which is undefined behavior in general.
Therefore, if you use pass-by-value, you clearly state to your caller that the object will be copied and it should not be polymorphic.
Another reason can be performance. If the class is small and its copy-constructor trivial, it might be faster to copy it than to use indirection (think of an int-like class). There are other cases where pass-by-value can be faster, but in non-inline cases they are rarer.
I do think however that none of these is the real reason and the developers just picked this out of the blue...
... because the real WTF (as they say) is that the operator# should be declared as free functions to allow argument promotion of the left-hand side argument ...
So if they didn't follow this rule, why would they bother with usual argument passing style ?

So that object doesn't get copied from the original parameter. In fact, the preferred way is to pass object as const, and to make operator+ as const member operator:
class_name class_name :: operator + (const class_name& object) const;

Passing a reference is much faster than copying the whole instance of your class of course.
Also, if there is no copy constructor defined for the class, it could be dangerous to copy it (default copy constructor will just copy pointers and the destructor will delete them for example).
When passing classes to a method or operator, the best is to always pass a reference. You can declare it const to be sure it is not modified to avoid side effects.

Related

C++ overloading the equality operator. Should I write my function to accept argument passed by reference or value?

I want to overload the == operator for a simple struct
struct MyStruct {
public:
int a;
float b;
bool operator==( ) { }
}
All the examples I'm seeing seem to pass the value by reference using a &.
But I really want to pass these structs by value.
Is there anything wrong with me writing this as
bool operator== (MyStruct another) { return ( (a==another.a) && (b==another.b) ); }
It should really not matter expect that you pay the penalty of a copy when you pass by value. This applies if the struct is really heavy. In the simple example you quote, there may not be a big difference.
That being said, passing by const reference makes more sense since it expresses the intent of the overloaded function == clearly. const makes sure that the overloaded function accidentally doesn't modify the object and passing by reference saves you from making a copy. For == operator, there is no need to pass a copy just for comparison purposes.
If you are concerned about consistency, it's better to switch the other pass by value instances to pass by const ref.
While being consistent is laudable goal, one shouldn't overdo it. A program containing only 'A' characters would be very consistent, but hardly useful. Argument passing mechanism is not something you do out of consistency, it is a technical decision based on certain technical aspects.
For example, in your case, passing by value could potentially lead to better performance, since the struct is small enough and on AMD64 ABI (the one which is used on any 64bit Intel/AMD chip) it will be passed in a register, thus saving time normally associated with dereferencing.
On the hand, in your case, it is reasonable to assume that the function will be inlined, and passing scheme will not matter at all (since it won't be passed). This is proven by codegen here (no call to operator== exist in generated assembly): https://gcc.godbolt.org/z/G7oEgE

Test a C++ object validity as though it was a pointer

Let's say I have an object which may not be properly initialized, but it's not simply a null pointer to object; it's an object with empty or uninitialized members. But I want to check it in as readable a manner as if it was a pointer:
if (Object) use(Object);
For example, Object may have an int field which, if 0, is considered uninitialized. Then, I can make an overload of the ! operator like this:
bool operator!() const {return intField == 0;}
I can use it like so:
if (! Object) initialize (Object);
The thing is, if I want to test for the opposite condition (non-null-ness), I can't do just this:
if (Object)...
I only find awkward possibilities:
if (! (! Object))... // awful
if (Object.notNull()) // not so bad
The one closest to my wishes is confusing:
bool operator()() {return intField != 0;}
if (Object())... // it looks a lot like an argument-less constructor
AFAIK, there is no bool-returning empty operator (something like bool operator() {...}) or any other trick or idiom that can achieve this.
Any ideas of a readable solution other than the notNull() method? Thanks.
You can provide a type conversion operator, to allow conversion to bool:
explicit operator bool() const {return intField != 0;}
This allows it to be used in boolean contexts, such as if conditions. explicit is optional, but a good idea to prevent potentially confusing conversions to numeric types.
An alternative approach is to use Boost.Optional or similar, to make any type nullable.
I think you want to be careful by using operator overloading to indicate validity or an initialized state--especially if you will ever hold a pointer or reference to an object of this type.
For this case, I would recommend the following explicit notation:
if (Object.isValid()) use(Object);
This way, it's obvious to the next person who reads your code exactly what you're doing here. Operator overloading should always be obvious to the person using it, and a true/false check on an object means it exists or not, not necessarily if it's valid or not.

boost::optional not letting me reassign const value types

It seems to me there should be four variants of boost::optional
optional<Foo> => holds a mutable Foo and can be reassigned after initialization
optional<Foo const> const => holds a const Foo and can't be reassigned after initialization
optional<Foo> const => (should?) hold a mutable Foo but can't be reassigned after initialization
optional<Foo const> => (should?) hold a const Foo and can be reassigned after initialization
The first 2 cases work as expected. But the optional<Foo> const dereferences to a const Foo, and the optional<Foo const> doesn't allow reassignment after initialization (as touched upon in this question).
The reassignment of the const value types is specifically what I ran into, and the error is:
/usr/include/boost/optional/optional.hpp:486: error: passing ‘const Foo’ as ‘this’ argument of ‘Foo& Foo::operator=(const Foo&)’ discards qualifiers [-fpermissive]
And it happens here:
void assign_value(argument_type val,is_not_reference_tag) { get_impl() = val; }
After construction, the implementation uses the assignment operator for the type you parameterized the optional with. It obviously doesn't want a left-hand operand which is a const value. But why shouldn't you be able to reset a non-const optional to a new const value, such as in this case:
optional<Foo const> theFoo (maybeGetFoo());
while (someCondition) {
// do some work involving calling some methods on theFoo
// ...but they should only be const ones
theFoo = maybeGetFoo();
}
Some Questions:
Am I right that wanting this is conceptually fine, and not being able to do it is just a fluke in the implementation?
If I don't edit the boost sources, what would be a clean way to implement logic like in the loop above without scrapping boost::optional altogether?
If this does make sense and I were to edit the boost::optional source (which I've already had to do to make it support movable types, though I suspect they'll be doing that themselves soon) then what minimally invasive changes might do the trick?
So basically the problem seems to be related to this note in the documentation for optional& optional<T (not a ref)>::operator= ( T const& rhs ):
Notes: If *this was initialized, T's assignment operator is used, otherwise, its copy-constructor is used.
That is, suppose you have boost::optional<const Foo> theFoo;. Since a default constructed boost::optional<> is empty, the statement:
theFoo=defaultFoo;
should mean "copy construct defaultFoo into theFoos internal storage." Since there's nothing already in that internal storage, this makes sense, even if the internal storage is supposed to house a const Foo. Once finished, theFoo will not be empty.
Once theFoo contains a value, the statement
theFoo=defaultFoo;
should mean "assign defaultFoo into the object in theFoos internal storage." But theFoos internal storage isn't assignable (as it is const), and so this should raise a (compile time?) error.
Unfortunately, you'll notice the last two statements are identical, but conceptually require different compile time behavior. There's nothing to let the compiler tell the difference between the two, though.
Particularly in the scenario you're describing, it might make more sense to define boost::optional<...>'s assignment operator to instead have the semantics:
If *this was initialized, its current contents are first destroyed. Then T's copy-constructor is used.
After all, it's entirely possible to invoke T's assignment operator if that's what you really want to do, by saying *theFoo = rhs.
(1) One's opinion on what the behavior "should" be depends on whether optionals are "a container for zero or one objects of an arbitrary type" or "a thin proxy for a type, with an added feature". The existing code uses the latter idea, and by doing so, it removes half of the "four different behaviors" in the list. This reduces the complexity, and keeps you from unintentionally introducing inefficient usages.
(2) For any Foo type whose values are copyable, one can easily switch between mutable and immutable optionals by making a new one. So in the given case, you'd get it as mutable briefly and then copy it into an immutable value.
optional<Foo> theMutableFoo (maybeGetFoo());
while (someCondition) {
optional<Foo const> theFoo (theMutableFoo);
// do some work involving calling some methods on theFoo
// ...but they should only be const ones
// ...therefore, just don't use theMutableFoo in here!
theMutableFoo = maybeGetFoo();
}
Given the model that it's a "thin proxy" for a type, this is exactly the same kind of thing you would have to do if the type were not wrapped in an optional. An ordinary const value type needs the same treatment in such situations.
(3) One would have to follow up on the information given by #Andrzej to find out. But such an implementation change would probably not perform better than creating a new optional every time (as in the loop above). It's probably best to accept the existing design.
Sources: #R.MartinhoFernandez, #KerrekSB
To answer your three questions:
The implementation follows the design philosophy that optional's assignment uses T's assignment; and in this sense, the implementation is fine.
optional was designed with possible extensions in mind. Optional is only an interface for the underlying class optional_base. Instead of using optional you can derive your own class from optional_base. optional_base has a protected member construct, which does almost what you need. You will need a new member, say reset(T) that firsts clears the optional_base and then calls construct().
Alternatively, you can add member reset(T) to optional. This would be the least intrusive change.
You could also try the reference implementation of optional from this proposal.

Combined Operator Overloading in C++?

Is it possible to overload operators in such a way that you can capture a specific combination of them? For example lets say I have a custom object myObject of type MyType where [] is already overloaded to pass such calls down to a map object. That said, in the case of the following code:
int value = myObject["someProp"];
I'm already overloading [] but in this case I'd like to know when [] is being called on the object in an assignment, with a reference to the type of object that the property lookup is to be assigned to. This way I can cast the value coming out of the dynamic property lookup and so on and so forth. Any input is appreciated!
For more insight into exactly what I'm trying to accomplish, see this related question of mine.
No, you can't overload on the return type, or on the context in which the call appears (e.g. in an assignment etc).
You could, however, return a proxy object that would have a bunch of overloaded conversion operators. Without seeing what you intend to do, it's hard to say how far you might be able to get with this approach, or whether it's even a sane thing to do.
If you want type deduction for things like this, your best bet is to overload operator() instead, and pass in the thing you're going to be assigning to as a dummy parameter, i.e.:
MyType myObject;
int value = myObject("someProp", value);
I've made something like this work pretty well in the past. In particular, see e.g.:
https://github.com/sgolodetz/hesperus2/blob/master/source/engine/core/hesp/objects/base/ObjectManager.tpp
In principle, it's rather straightforward to do: all that is needed is
for your operator to return a proxy which then overloads the operators
you want to catch. In practice, it can cause more than a few problems;
readers will expect (a op1 b) op2 c to have
the same semantics as T tmp(a ip1 b); tmp op2
c. There are some common exceptions, however:
The operator[] in a multi-dimensional array will often return a
proxy which defines an operator[] itself, in order to support [][]
correctly.
More generally, a container which for whatever reasons needs to know
when a value is modified will have an operator[] which returns a
proxy; within the proxy, assignment is defined as setting the value in
the owning container, and there will be a convertion operator to the
value type, for use in rvalue contexts. Of course, this means that
things like m[i][j].funct() don't work; typically, however, this sort
of thing is used for matrices of numeric types, where member functions
aren't that relevant.
In contexts where it is desirable to support overload resolution based
on the target type (your example), the function can return a proxy with
overloaded conversion operators. You want to be extremely careful with
this—overloaded conversion operators are often a recipe for
overload resolution ambiguities&rdash;but there are enough exceptions
that this situation bears mentionning. (Important, here, is that the
results of the operator will amost always be used to intialize or to
assign to a specific object, the type of which determines which
conversion operator will be called.)
BTW: I might mention that in the example you give, there is no
assignment; it is a classical initialization. In this case, defining
the operator[] to return a proxy which defines operator int() const
would do the trick very well. Before going this route, however, you
should very definitely consider all of the use cases of your class, and
ensure that there are none in which the actual target type is ambiguous.
The other answers are basically correct that you can't do it. aix hints at a solution of a custom return type with overloaded conversion operators, but rightly indicates it isn't a sane thing to do. I've ventured down this path quite often and ultimately implicit conversions, and sequences of conversions, and ambiguities will bite you in you in the behind.
I've had a need of this quite often though. Ultimately I end up going for a series of overloaded functions, or templates, depending on your needs, perhaps like this:
void lookup( int& v, char const * name );
void lookup( double& c, char const * name );
In the template case I created global converters and did the below member function:
template<T>
void lookup( T&v, char const* name ) { v = convert<T>( get(name) ); }
If you want to keep the return value as the lookup you'll have to explicitly call a templated function.
template<T> T get( char const * name ) { ... }
//use
int a = obj.get<int>( "name" );
double b = obj.get<double>( "floaty" );
No, you can't do that.
Moreso, madness that way lies!

Passing temporaries as LValues

I'd like to use the following idiom, that I think is non-standard. I have functions which return vectors taking advantage of Return Value Optimization:
vector<T> some_func()
{
...
return vector<T>( /* something */ );
}
Then, I would like to use
vector<T>& some_reference;
std::swap(some_reference, some_func());
but some_func doesn't return a LValue. The above code makes sense, and I found this idiom very useful. However, it is non-standard. VC8 only emits a warning at the highest warning level, but I suspect other compilers may reject it.
My question is: Is there some way to achieve the very same thing I want to do (ie. construct a vector, assign to another, and destroy the old one) which is compliant (and does not use the assignment operator, see below) ?
For classes I write, I usually implement assignment as
class T
{
T(T const&);
void swap(T&);
T& operator=(T x) { this->swap(x); return *this; }
};
which takes advantage of copy elision, and solves my problem. For standard types however, I really would like to use swap since I don't want an useless copy of the temporary.
And since I must use VC8 and produce standard C++, I don't want to hear about C++0x and its rvalue references.
EDIT: Finally, I came up with
typedef <typename T>
void assign(T &x, T y)
{
std::swap(x, y);
}
when I use lvalues, since the compiler is free to optimize the call to the copy constructor if y is temporary, and go with std::swap when I have lvalues. All the classes I use are "required" to implement a non-stupid version of std::swap.
Since std::vector is a class type and member functions can be called on rvalues:
some_func().swap(some_reference);
If you don't want useless copies of temporaries, don't return by value.
Use (shared) pointers, pass function arguments by reference to be filled in, insert iterators, ....
Is there a specific reason why you want to return by value?
The only way I know - within the constraints of the standard - to achieve what you want are to apply the expression templates metaprogramming technique: http://en.wikipedia.org/wiki/Expression_templates Which might or not be easy in your case.