Search code examples
c++implicit-conversion

Why implicit conversion doesn't work when inserting to map


I have a structure that is implicitly convertable to the type that is acceptable by the std::map::insert() function.

I use a structure as-is, but I have compilation error:

no overloaded function could convert all the argument types

However, if I explicitly convert the structure using static_cast, it is accepted.

My question is, why does implicit conversion not work here?

Example code:

struct MyStruct
{
    MyStruct(std::string s, int i) : data(s, i) {}
    operator std::pair<std::string, int>() const
    {
        return data;
    }

private:
    std::pair<std::string, int> data;
};

MyStruct my_val1("hello", 4);
MyStruct my_val2("world", 2);

std::map<std::string, int> my_map {};
my_map.insert(static_cast<std::pair<std::string, int>>(my_val1)); // compiles
my_map.insert(my_val2);                                           // not compiles

Solution

  • Your issue is that value_type of my_map is std::pair<const std::string, int>, not std::pair<std::string, int> like you have for your conversion operator.

    This means that converting my_val2 requires two user-defined conversions1 to get to std::pair<const std::string, int>, but you are only ever allowed to have up to one user-defined conversion in an implicit conversion sequence.

    The static_cast works as that is an explicit cast, so there is just the one implicit user-defined conversion to go from std::pair<std::string, int> to std::pair<const std::string, int>.


    Changing your operator to operator std::pair<const std::string, int>() const will allow my_map.insert(my_val2); to compile, as seen in this live example.


    1: even standard library types are considered user-defined. Non user-defined types are things that the core language supports, like int.