views:

551

answers:

3

In C++, can you have a templated operator on a class? Like so:

class MyClass {
public:
    template<class T>
    T operator()() { /* return some T */ };
}

This actually seems to compile just fine, but the confusion comes in how one would use it:

MyClass c;
int i = c<int>(); // This doesn't work
int i = (int)c(); // Neither does this*

The fact that it compiles at all suggests to me that it's doable, I'm just at a loss for how to use it! Any suggestions, or is this method of use a non-starter?

+15  A: 

You need to specify T.

int i = c.operator()<int>();

Unfortunately, you can't use the function call syntax directly in this case.

Edit: Oh, and you're missing public: at the beginning of the class definition.

avakar
Nice. Kudos on the quick and accurate answer! Unfortunately that's probably to verbose for my uses (since my code is intended to be called by others I want to avoid confusion) so I'll just have to find another route. Thanks again!
Toji
Yes, you're probably better off defining a `get` method instead of `operator()`. Then you could write `c.get<int>()`.
avakar
Actually, there is an idiom flying around that's used by many: free get function (tuples use `get<N>(some_tuple)`, boost.variant uses `get<T>(some_variant)`). So yours would look like `get<T>(c)`, with `get` being defined in `MyClass`'es namespace).
Johannes Schaub - litb
In this case I needed both a call that returned a value and one that didn't. I implemented *Evaluate<type>()* for the returning version, and *Execute()* for the non-returning, and then allowed the user to call the () operator as an alternative to Evaluate. (The names make sense in context, since they are executing functions defined in a script.) So essentially, yes, I implemented a get function :) Thanks for all the suggestions!
Toji
+10  A: 

You're basically right. It is legal to define templated operators, but they can't be called directly with explicit template arguments.

If you have this operator:

template <typename T>
T operator()();

as in your example, it can only be called like this:

int i = c.operator()<int>();

Of course, if the template argument could be deduced from the arguments, you could still call it the normal way:

template <typename T>
T operator()(T value);

c(42); // would call operator()<int>

An alternative could be to make the argument a reference, and store the output there, instead of returning it:

template <typename T>
void operator()(T& value);

So instead of this:

int r = c.operator()<int>();

you could do

int r;
c(r);

Or perhaps you should just define a simple get<T>() function instead of using the operator.

jalf
+1  A: 

Aren't you thinking of

class Foo {
    public:
    template<typename T>
    operator T() const { return T(42); }
};

Foo foo;

int i = (int) foo; // less evil: static_cast<int>(foo);
MSalters