operator()

Hello C++ guru's:)) Tell me please, could operator() be overloaded by return type?
Last edited on
No. Nothing can be overloaded by return type.

The overload has to be determined by the parameters passed in.


EDIT:

Of course... 2 different overloads can have 2 different return types ... but those overloads must also take different parameters.


EDIT 2:

And other things can affect overloads... like 'const' and 'volatile' keywords.
Last edited on

EDIT:

Of course... 2 different overloads can have 2 different return types ... but those overloads must also take different parameters.


Thank you so much! of course... next time i should write in the beginner section maybe:)
Class membership is another factor in Overload resolution. Not to over complicate things on you OP, but that operator can be defined as taking the exact same parameters in two separate classes and return a different data type from each one. This isn't exactly overloading by return type; but it may be a solution for your problem.
Not to over complicate things on you OP, but that operator can be defined as taking the exact same parameters in two separate classes and return a different data type from each one.



Uhh... doesn't one of the parameters have to be the class?

In which case, different classes = different parameters.


Besides, even if you have 2 () operators which take the same params in 2 different classes, you'll get 'ambiguous call' linker errors if you try to actually use them.
Not if they're direct memebers:

1
2
3
4
5
6
7
8
9
struct TEST_A
{
  int operator()(int i) {return 5;}
};

struct TEST_B
{
  char operator()(int i) {return 'A';}
};
Yeah... but... you need an object.... which is the implied first parameter.
I know what you mean now. I was thinking in terms of cl's name decoration scheme in which case the class is not listed along with the other parameters which is why I did not consider it to be one.
Sorry I missed this one.

True: The language does not allow does not allow you to directly overload on return type:

1
2
3
4
5
struct dumbonium
{
  int  operator () const { return -7; }
  char operator () const { return 'A'; }  // ERROR!
};

However, it is entirely possible to cheat. Yup. My favorite, non-Boost.Any way to do it is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>

struct awsomium
{
  operator int    () const { return -7; }
  operator char   () const { return 'A'; }
  operator double () const { return 3.141592; }
};

int main()
{
  awsomium a;
  int  x = a;
  char c = a;
  std::cout << x << ", " << c << ", " << (double)a << "\n";
}

The major caveat is that you must be explicit about the return type you desire, otherwise type promotion rules will kick in and confuse you.


As an aside, the most useful reason to do this kind of thing is for "returning" a container from a function. For example, suppose you have a fancy "split" function, which takes a string and converts it into a list of strings.

Note -- this code is fairly simplified to keep other confusing things out of the discussion.

1
2
3
4
5
6
7
8
9
10
template <typename Container>
Container&
split(
  Container&         result,
  const std::string& s,
  const std::string& delimiters
  ) {
  ...
  return result;
  }
Used thus:

1
2
3
string s = "Hello world!";
vector <string> words;
split( words, s, " " );

What we'd like to say is something like this:

1
2
string s = "Hello world!";
vector <string> words = split( s, " " );

For that, we'll need two helpers:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// A struct that overloads on "return" type
stuct split_helper
{
  const std::string& s;
  const std::string& delimiters;

  split_helper( const std::string& s, const std::string& delimiters ):
    s( s ), delimiters( delimiters )
    { }

  template <typename Container>
  operator Container () const
  {
    Container result;
    return split( result, s, delimiters );
  }
};

// A make-functor
inline
split_helper 
split(
  const std::string& s,
  const std::string& delimiters
  ) {
  return split_helper( s, delimiters );
  }

Voila!

The method still has issues, of course -- careless use can confuse your compiler.

Also useful are the <type_traits> library and the SFINAE principle.

Hope this helps.
That's the cast operator, though.. Not the () operator.

Though you are correct, I forgot about the cast operator when I said "nothing can be overloaded by return type". Touche.
Topic archived. No new replies allowed.