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!
Related
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.
As pointed out by this article, it is impossible to overload the comparison operator (==) such that both sides could take primitive types.
"No, the C++ language requires that your operator overloads take at least one operand of a "class type" or enumeration type. The C++ language will not let you define an operator all of whose operands / parameters are of primitive types." (parashift)
I was wondering:
**If I really-really needed to compare two primitives in a non-standard way using the ==, is there a way to implicitly cast them to some other class?
For example, the following code will work for const char* comparison, but it requires an explicit cast. I would prefer to avoid explicit casts if possible.
// With an explicit cast
if(string("a")=="A") // True
// Without the cast
if("a"=="A") // False
// An example overloaded function:
bool operator == (string a, const char* b)
{
// Compares ignoring case
}
Casting can be pretty clunky in some situations, especially if you need to do several casts inside a long expression. So that's why I was looking for a way to automatically cast the first input (or both) to a sting type.
Edit 1:
Another way to do this is to write an isEqual(const char* a, const char* b) function, but I want to avoid this because it will result in a mess of parenthesis if I were to use it inside of a large if-statement. Here's an oversimplified example that still shows what I mean:
if (str1 == str2 || str1 == str3 || str2==str4)
As opposed to:
if (isEqual(str1,str2) || isEqual(str1,str3) || isEqual(str2,str4))
Edit 2:
I know there exist many ways to achieve the desired functionality without overloading the ==. But I looking specifically for a way to make the == work because I then could apply the knowledge to other operators as well.
This question is in fact closely related to the Wacky Math Calculator question I asked a few weeks ago, and being able to overload the == will help make the code look considerably nicer (visually, but perhaps not in a "clean code" way).
And that's I wanted to ask this question here on SO, in case someone had a cool C++ trick up their sleeve that I didn't know about. But if the answer is No then that's fine too.
You could certainly write one or more free functions to do your comparison. It doesn't have to be an operator overload.
for example:
bool IsEqual(const char* a, const string& b)
{
// code
}
bool IsEqual(const string& a, const char* b)
{
// code
}
and so on.
If the types of the operands are given, and you cannot add an overload for equality, because
It is simply not overloadable, because all are primitive types
There is already an overload, which does not do what you want
You do not want to risk violation of the ODR because someone else could be pulling the same kind of stunts you do (In which case a TU-local override might work, aka free file-local. Be aware of adverse effects on templates.)
there are just two options:
Use a wrapper and overload all the operators to your hearts content.
Use a function having the desired behavior explicitly and just forget about the syntax-sugar.
BTW: That standard-library containers and algorithms often can be customized three ways:
Using a type having overloaded operators
Having the used standard traits-class specialized
Providing a different traits-class.
No, there's no way to implicitly cast the primitive types the way you want.
The only way to achieve the desired functionality is either by explicitly casting the inputs into another class as stated in the question, or by creating a free function as shown by #Logicat.
I have a function multiply and a function sum, with special characteristics, implemented on a given class i.e. (EngineManager). These functions add and multiply integers in a special fashion and they give away as a result a different class i.e. (StandardShare). When I try to implement the overload directly, the compiler promts:
Overloaded 'operator+' must be a unary or binary operator (has 3 parameters)
I understand that the third parameter it is referring to is the this pointer. But as I cannot implement them as free methods, given that they use functions from the hos class i.e. (EngineManager), what alternative do i have.
The code should look like this:
class EngineManager {
public function Shares::StandardShare* addShares(int a, int b){
//Does Something......
};
inline Shares::StandardShare* operator +(int a, int b){
return this->addShares(a,b);
};
};
Thanks in advance
This is neither possible, nor a good idea.
It's not possible not only because overloading the + operator that takes two arguments must be a free function, but also because the type of both arguments cannot be a simple built-in type (like int). At least of them must be a class or enumerator type.
It's not a good idea because, even if it were possible, the effect of this would not be confined to the class. The overloaded operator would be called everywhere where you include the header file of your class. So suddenly all integer additions across your program would break. But most importantly, it's not a good idea because it breaks the intuitive meaning of using the + operators with two integers. If you change that meaning, you're only creating confusion for no good reason.
Can I use:
MyClass& MyClass::operator++ () {
a++; // private var of MyClass
return (*this);
}
Or it can be:
MyClass MyClass::operator++ ();
What's the difference?
Thanks for answers. I have another issue.
Many people do something like that:
MyClass& MyClass::operator++();
MyClass MyClass::operator++(int);
Isn't it illogical? Please give some examples if you can.
I know that the first version is pre-increment and the second is post-increment, but i ask why the first one returns reference but the second one not? It is in the same code (class), and the same use of the code.
No, you don't have to return the reference to your object when you overload the pre-increment operator. In fact you may return anything you'd like, MyClass, int, void, whatever.
This is a design issue -- you must ask yourself what is the most useful thing to the users of your class that you are able to return.
As a general rule, class operators are the most useful when they cause the least confusion, that is, when they operate the most like operators on basic types. In this case, the pre-increment operator on a basic type:
int i = 7;
j = ++i;
increments the variable and then returns the new value. If this is the only use you want MyClass to have, then returning a copy of your class is sufficient.
But, the pre-increment operator on a basic type actually returns an lvalue. So, this is legal:
int i = 7;
int *p = &++i;
If you want to support an operation like this, you must return a reference.
Is there a specific reason that you don't want to return a reference? Is that not a well-formed concept for your particular class? If so, consider returning void. In that case, this expression: ++myObject is legal, while this myOtherObject = ++myObject is not.
You can return whatever you want. void, reference to self, copy of self, something else. Whichever you prefer (or need).
If you plan using the ++ operator in chained expressions (like (++obj).something()) then return a reference. In you don't, then void is just fine.
Remember that in the end, operators are just like normal methods: you can do whatever you want with them, provided you respect their prototype.
For question two:
Prefix returns a reference, as expected.
Postfix returns a copy to be consistent with the behavior of the postfix operator(s).
Break it down simply to int:
int c = 0;
if(++c)
{
// true, prefix increments prior to the test
}
c = 0;
if(c++)
{
// false, c now == 1, but was incremented after the test
}
Implementing this behavior in a class requires a copy be returned because the postfix operator will have modified the state of the object.
If the program does not need true postfix operation, you are free of course to implement how you wish. While there are standard ways of writing these operators (that are understood by most C++ programmers), there's nothing actually stopping you from implementing this in different ways.
The argument provided about incorrect functionality surrounding (obj++)++ is not really important, as that code won't even compile for POD types (in Visual Studio 2010, at least), because for POD types, a copy is returned and that temporary copy cannot be used alone as an l-value.
However, for the prefix operator a reference is the preferred return as that allows the proper behavior for chaining the operation (++(++obj)).
Its not compulsory, but we should try to make operator overloading intuitive and it should work as per the operator which is being overloaded.
If we do
int i = 10;
i++ = 0
Then second statement is not allowed it says it requires lvalue as i++ denotes older state of i not a storage ...
while ++i = 0 perfectly works fine ..
so just to keep it in sync with actual operators prefix version had to return refence so that its return value may be treated as lvalue in expressions.
Yes, you should return by reference. No need for the parenthesis around *this.
EDIT: Replying to your comment... You don't have to return by reference. But in general we follow some guidelines which make our classes behave "as expected" when compared to the builtin semantics of such operators. You might wanna take a look at http://www.parashift.com/c++-faq-lite/operator-overloading.html.
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.