Unordered map vs map

105 views Asked by At

Does anyone know why Dict class is invalid but Dict2 is fine?


#include <string>
#include <unordered_map>
#include <map>
#include <variant>

class Dict
{
public:
    Dict() {}

private:
    std::unordered_map<std::string, std::variant<Dict, std::string>> data;
};

class Dict2
{
public:
    Dict2() {}

private:
    std::map<std::string, std::variant<Dict2, std::string>> data;
};

int main()
{
    Dict d;
    Dict2 d2;
    return 0;
}

I get an error of

‘value’ is not a member of ‘std::is_trivially_move_constructible<Dict>’.

I looked up the concept of trivially move and copy constructible, as I understood, the move contructor should be defined or deleted. I am guessing it is because of using std::unordered_map with std::variant and the the compiler doesn't know how an object should be moved. But I am not sure if I have understood it correctly.

1

There are 1 answers

2
Igor Tandetnik On BEST ANSWER

I believe the behavior is undefined in both cases. Dict2 just happens to compile by accident of implementation; "seems to work" is one possible manifestation of undefined behavior.

[res.on.functions]/1 In certain cases (replacement functions, handler functions, operations on types used to instantiate standard library template components), the C++ standard library depends on components supplied by a C++ program. If these components do not meet their requirements, this International Standard places no requirements on the implementation.

[res.on.functions]/2 In particular, the effects are undefined in the following cases:
...
(2.5) — if an incomplete type (6.9) is used as a template argument when instantiating a template component, unless specifically allowed for that component.

Dict and Dict2 are incomplete types until the closing brace of their definitions. std::variant doesn't specifically allow being instantiated with an incomplete type.