c++ type cast operator overloading and implicit co

2019-01-28 08:03发布

问题:

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.

回答1:

[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.



回答2:

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;
}