Home > Software design >  Store struct with deleted copy and move constructor in container
Store struct with deleted copy and move constructor in container

Time:10-25

I have a struct with deleted copy and move constructors and operators, but I want to add this struct to a container. How can I solve this problem?

class NonCopyable {
public:
    NonCopyable() = default;
    NonCopyable(NonCopyable &&) = default;
    NonCopyable(const NonCopyable&) = delete;
    NonCopyable& operator=(const NonCopyable&) = delete;
    NonCopyable& operator=(NonCopyable&&) = default;
};

class NonMovable {
public:
    NonMovable() = default;
    NonMovable(NonMovable &&) = delete;
    NonMovable(const NonMovable&) = default;
    NonMovable& operator=(const NonMovable&) = default;
    NonMovable& operator=(NonMovable&&) = delete;
};

struct Data : NonCopyable, NonMovable
{
    Data(std::string str, int data)
        : m_str(std::move(str)), m_data(data) {}
private:
    std::string m_str;
    int m_data; 
};

int main(int argc, char** argv)
{
    std::unordered_map<std::string, Data> table;
    table.emplace("test", Data{"data",10});
    return 0;
}

Error:

 /Library/Developer/CommandLineTools/usr/bin/../include/c  /v1/memory:1881:31: error: no matching constructor for initialization of 'std::__1::pair<const std::__1::basic_string<char>, Data>'
    ::new((void*)__p) _Up(_VSTD::forward<_Args>(__args)...);

CodePudding user response:

table.emplace("test", Data{"data",10}) will still call the move constructor of Data, you need to use std::piecewise_construct to construct the pair:

std::unordered_map<std::string, Data> table;
table.emplace(std::piecewise_construct, 
              std::make_tuple("test"), 
              std::make_tuple("data",10));

Demo.

According to cppreference:

 template<class... Args1, class... Args2>
 constexpr pair(std::piecewise_construct_t,
                std::tuple<Args1...> first_args,
                std::tuple<Args2...> second_args);

Forwards the elements of first_args to the constructor of first and forwards the elements of second_args to the constructor of second. This is the only non-default constructor that can be used to create a pair of non-copyable non-movable types.

CodePudding user response:

A more terse alternative to piecewise_construct:

table.try_emplace("test", "data", 10);
  •  Tags:  
  • c
  • Related