简体   繁体   中英

Overload resolution works on functions, but not with implicit constructor parameters

This code shows a basic wrapper class for the __int32 and bool type. My intention is to extend basic types with methods and custom operators, etc.

Each class has one implicit constructor, allowing to assign an __int32 to an Int32 type implicitly. This works well, until there is a function overload accepting both Int32 or Boolean .

While a function with the overloads __int32 and bool compiles and works, the function with the classes as overloads results in Ambiguous calls to overloaded function .

My question: Is there a way to solve this properly, so I can implement wrapper classes for basic types without overload resolution problems and without the need for explicit casts by the caller?

class Boolean
{
private:
    bool _Value = false;
public:
    Boolean(bool value)
    {
        _Value = value;
    }
};

class Int32
{
private:
    __int32 _Value = 0;
public:
    Int32(__int32 value)
    {
        _Value = value;
    }
};

void AmbiguousFunc(const Int32 &x) { }
void AmbiguousFunc(const Boolean &x) { }

void NotAmbiguous(__int32 x) { }
void NotAmbiguous(bool x) { }

int main(int argc, char *argv[])
{
    AmbiguousFunc(123);         // Ambiguous calls to overloaded function
    AmbiguousFunc((Int32)123);  // works
    NotAmbiguous(123);

    return 0;
}

The problem is, given AmbiguousFunc(123); , 123 could be converted to bool (standard conversion), then converted to Boolean (user-defined conversion); which has the same ranking with the user-defined conversion from 123 to Int32 , then the calling is ambiguous between AmbiguousFunc(const Int32 &) and AmbiguousFunc(const Boolean &) .

You can change the constructors as template, and restrict them to accept only appropriate types.

class Boolean
{
private:
    bool _Value = false;
public:
    // accept bools only; no __int32s
    template <typename T, std::enable_if_t<std::is_same_v<T, bool>>* = nullptr>
    Boolean(T value)
    {
        _Value = value;
    }
};

class Int32
{
private:
    __int32 _Value = 0;
public:
    // accept __int32s only; no bools
    template <typename T, std::enable_if_t<std::is_same_v<T, __int32>>* = nullptr>
    Int32(T value)
    {
        _Value = value;
    }
};

LIVE

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM