user3799309
user3799309

Reputation: 41

c++ type cast operator overloading and implicit conversions

if I'm overloading the type cast operator, I'm running into compile errors when an implicit conversion is needed and one can't be found. Consider the simple example where I have a wrapper class that contains a type (in this case a long long):

class my_wrapper
{
    long long state;

public:
    my_wrapper(long long _in) : state(_in) {}

    my_wrapper& operator=(const long long rhs)
    {
        state = rhs;
        return *this;
    }

    operator long long()
    {
        return state;
    }
};

The question now is that if I want to cast in code to something else (eg a void* ... assume that I'm on 64bit for this) the following does not work without specifying two casts:

my_wrapper x1 = my_wrapper(5ll);
void* i1 = (void *) x1; // Compile Error: no suitable conversion function exists
void* i1 = (void *) (long long) x1; // Works

vs. if I had written something like:

long long i1 = 5ll;
void* i2 = (void *) i1; // Works

Not a big deal, but just curious if its possible to specify that the "operator long long()" should be used as the default if there is no other conversion.

Upvotes: 4

Views: 10050

Answers (2)

Axalo
Axalo

Reputation: 2953

Since (void *)x1 effectively gives you the address of x1.state you could simply implement a void * cast operator.

Like so:

operator void *()
{
    return &state;
}

The drawback of this is that you can now convert my_wrapper to void * implicitly as well.

Luckily, you can prevent this in C++11 by using the explicit specifier:

explicit operator void *()
{
    return &state;
}

Upvotes: 1

Columbo
Columbo

Reputation: 60979

[over.match.conv]/(1.1):

The conversion functions of S and its base classes are considered. Those non-explicit conversion functions that are not hidden within S and yield type T or a type that can be converted to type T via a standard conversion sequence (13.3.3.1.1) are candidate functions.

There is no standard conversion sequence from an integral type to void*1, thus the conversion operator is not a candidate.

You can try a conversion operator template:

template <typename T>
operator T()
{
    return T(state);
}

1 An integer literal with value zero is the exception.

Upvotes: 1

Related Questions