user562566
user562566

Reputation:

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.

Upvotes: 0

Views: 834

Answers (5)

edA-qa mort-ora-y
edA-qa mort-ora-y

Reputation: 31861

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" );

Upvotes: 1

James Kanze
James Kanze

Reputation: 153909

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.

Upvotes: 1

NPE
NPE

Reputation: 500327

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.

Upvotes: 5

Stuart Golodetz
Stuart Golodetz

Reputation: 20616

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

Upvotes: 1

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385144

No, you can't do that.

Moreso, madness that way lies!

Upvotes: 0

Related Questions