7

I've run into an interesting issue with MSVC. The following code does not compile with MSVC:

#include <vector>
#include <unordered_map>
#include <memory>
#include <string>

struct S {
    explicit S(const std::string&);

    // S(S&&) = default;

    std::vector<std::unique_ptr<int>> v;
    std::unordered_map<int, int> a;
    std::string s;
};

std::vector<S> foo() {
    std::vector<S> s;
    s.emplace_back("hello");
    s.emplace_back("world");
    return s;
}

https://www.godbolt.ms/z/pQnKwD

However, it does compile when either a defaulted move constructor is provided, or either the vector or the unordered_map are commented out. Commenting out the emplace_back statements also "solves" the problem. The problem does not occur with GCC or Clang, interestingly (http://coliru.stacked-crooked.com/a/a4e5590bd63c0de0).

What's going on here?

N. Shead
  • 3,828
  • 1
  • 16
  • 22
  • Which version of MSVC/cl? – Angew is no longer proud of SO Jan 29 '19 at 12:43
  • My version is 15.9.6 (cl 19.16), though apparently it's also a problem with the latest preview (and clang-cl). – N. Shead Jan 29 '19 at 12:44
  • I get a linker error when using this bit of code. – Duck Dodgers Jan 29 '19 at 12:54
  • I maybe wrong, but shouldn't this be `explicit S(const std::string&);` this instead `explicit S(const std::string&){}`. – Duck Dodgers Jan 29 '19 at 12:56
  • @JoeyMallone: obviously, as the `explicit` ctor is only declared. But the complaint was that this doesn't even compile. It does compile for you? – MSalters Jan 29 '19 at 12:57
  • Yes, but I was testing on a different configuration - Ubuntu with `gcc 7.3.0`. – Duck Dodgers Jan 29 '19 at 12:59
  • @JoeyMallone if you want it to link, then sure. You'd also need a `main` function, too. I left it out because it wasn't directly interesting to the problem I was having, though. – N. Shead Jan 29 '19 at 13:00
  • I added a `main()` also. And can compile, link and run this bit of code, albeit with `gcc 7.3.0`. – Duck Dodgers Jan 29 '19 at 13:00
  • 1
    Can you verify that this is not a problem with the `noexcept` shenanigans that MSVC has had for ages with (not-`noexcept`) moveable types in vectors? E.g. [this](https://stackoverflow.com/questions/47604029/move-constructors-of-stl-containers-in-msvc-2017-are-not-marked-as-noexcept)? It sounds very much like that issue, just in a different form... – Max Langhof Jan 29 '19 at 13:09
  • @MaxLanghof I don't think it is. For one, `std::unique_ptr` is noexcept-moveable, and so a `std::vector>` should be fine - there is only one member that's not noexcept-moveable. `std::unordered_map` is not noexcept-moveable, of course, so `S` is not noexcept-moveable. Except when you default the move constructor, in which case a `static_assert` still says it's not noexcept-moveable, but suddenly the `vector` works. It also works, I've discovered, when adding an (unused) `std::unique_ptr` member to `S`. Basically I'm just trying to work out _why_ all of this is happening. – N. Shead Jan 29 '19 at 21:37
  • 1
    ... having said that, I went looking based on what you said and found https://stackoverflow.com/questions/53168836/does-visual-studio-2017-need-an-explicit-move-constructor-declaration (which I'm ashamed I didn't find before), which does appear to be the same problem. – N. Shead Jan 29 '19 at 22:24

0 Answers0