Search code examples
c++c++17gcc9

c++ unorderd_map insert fails for value_type with atomic<bool> member


class strategy
{
    int id;
    std::atomic<bool> strategyStarted;
    int startTime;
    int endTime;

    void getStartTime() { return startTime; }
    void setStartTime(int sTime) { startTime = sTime; }
};

class strategyImpl{

    std::unordered_map<int, strategy> allStrategies;

    strategyImpl()
    {
        strategy newParams;
        newParams.id = 1;
        newParams.strategyStarted.store(false);
        newParams.startTime = 104500;
        newParams.endTime = 150500;
        allStrategies.insert(std::make_pair(newParams.id, newParams)); <--ERROR
    }
};

The problem arises when I try to insert/insert_or_assign/emplace to the unordered map allStrategies. Below are all the tried methods and their specific compiler errors.

allStrategies.insert(std::make_pair(newParams.id, newParams));

error: no matching function for call to ‘std::unordered_map<int, strategy>::insert(std::pair<int, strategy>)’

allStrategies.insert(std::pair<int, strategy>(newParams.id, newParams));

error: no matching function for call to ‘std::pair<int, strategy>::pair(int&, strategy&)’

allStrategies.insert(std::unordered_map<int, strategy>::value_type(newParams.id, newParams));

error: no matching function for call to ‘std::pair<const int, strategy>::pair(int&, strategy&)’

allStrategies.insert_or_assign(newParams.id, newParams);

error: use of deleted function ‘strategy& strategy::operator=(const strategy&)’

allStrategies.emplace(newParams.id, newParams);

error: no matching function for call to ‘std::pair<const int, strategy>::pair(int&, strategy&)’

I have tried all possible ways, but just am not able to insert into this unorderd_map. As far as I have read about these ways to add entries to a map, the value type is not required to have default constructor or copy constructor.

Please help me insert key value pairs to this map. How to do it?

Edit:

Added the problem causing member to class definition (it was omitted for conciseness) The root cause seems to be the member atomic<bool> strategyStarted

After removal of the member, insert(make_pair..) compiles fine.

Do I really have to do it without the atomic type?


Solution

  • So the basic problem is that the compiler isn't able to generate the default copy constructor because of the std::atomic. So you must write one for yourself. E.g.

    class strategy
    {
    public:
        strategy() = default;
        strategy(const strategy& rhs) 
            : id(rhs.id)
            , strategyStarted(rhs.strategyStarted.load())
            , startTime(rhs.startTime)
            , endTime(rhs.endTime)
        {
        }
        strategy& operator=(const strategy& rhs); // to do
        int id;
        std::atomic<bool> strategyStarted;
        int startTime;
        int endTime;
    
        int getStartTime() { return startTime; }
        void setStartTime(int sTime) { startTime = sTime; }
    };
    

    With that addition, all (or most) of your previous attempts should work.

    On the other hand you could write a move constructor, in which case try_emplace and similar will work.

    Whichever you choose you should also also add the corresponding assignment operator.