Search code examples
c++movestdvector

Any workarounds for this MSVC specific vector<unordered_map<Trivial, NonCopyable>> bug?


The following code does fail on MSVC but compiles on GCC and Clang, godbolt

#include <unordered_map>
#include <vector>
using namespace std;

struct NonCopyable
{
    NonCopyable() = default;
    NonCopyable(NonCopyable const &) = delete;
    NonCopyable(NonCopyable &&) = default;
};

int main()
{
    using Data = unordered_map<int, NonCopyable>;

    vector<Data> vec;

    vec.reserve(3);     // error
    vec.resize(3);      // error
    vec.emplace_back(); // error

    return 0;
}

This is the simplified version of the case I stumbled while working on my project. I was using MSVC from the beginning so I would prefer a workaround (if possible) rather than changing the compiler.

As I understand from the error messages, vector tries to copy construct a pair<Trivial, NonCopyable>. Which,, it shouldn't,,, but there is no way I know of to tell it not to do that :/

  • When Data = map<int, NonCopyable> MSVC fails with the same errors, while others compile.
  • All compilers are fine if I use Data = pair<int, NonCopyable>; so the container trying to copy construct a pair might be the unorderd_map 🤔
  • It works if I construct the vector with the correct size. However, I can not do that in my case.

Thanks


Solution

  • Apparently this is a long time know bug with a combination of MSVC STL implementation choices and Standard specifications...

    The issue I found when I was going to submit a bug report, from 2018: https://developercommunity.visualstudio.com/t/C2280-when-modifying-a-vector-containing/377449

    • This error is present in MSVC 2017 and after.
    • It seems like not going to be fixed. (see @Alex Guteniev's comment)

    The explanation given: https://www.reddit.com/r/cpp/comments/6q94ai/chromium_windows_builds_now_use_clangcl_by_default/dkwdd8l/

    • There is a workaround: vector<Wrapper<unordered_map<int, NonCopyable>>>, where the Wrapper is also a non-copyable type.