0

This code works in Visual Studio:

typedef struct {
    int a;
} data_t;

using datap_t = std::unique_ptr<data_t>;
using MyPair = std::pair<std::string, datap_t>;

int main() {
    data_t * pd1 = new data_t();
    MyPair p("tst", pd1); // This does not compile in gcc or clang
    // MyPair p2("tst", datap_t(pd1)); // This compiles

    return 0;
}

But clang and gcc give error:

error: no matching function for call to 'std::pair<const std::basic_string<char>, std::unique_ptr<data_t> >::pair(const char [3], data_t*&)

Here is the ideone to try.

The fact that I can call datap_t(pd1) and it compiles means the constructor is valid, so why is that template does not find a suitable match?

I was looking to add a key-value pair to a map using emplace and that is why I wanted to have this implicit conversion in the first place. Note that like Visual Studio the implicit conversion works for most other types, such as std::string from "raw string".

This answer looks relevant, but it talks about a fixed bug and is very old.

Max Feldkamp
  • 527
  • 1
  • 5
  • 16
dashesy
  • 2,596
  • 3
  • 45
  • 61
  • Don't use raw pointers. `auto pd1 = std::make_unique()`. – kfsone Jun 24 '16 at 23:17
  • @kfsone I do not, when dealing with external C libraries dealing with raw pointers is inevitable. Also, I am interested to see why this works in Visual Studio and not clang, not looking for how to make it work :) – dashesy Jun 24 '16 at 23:22

1 Answers1

4

The std::unique_ptr constructor that take a single raw pointer as input is marked as explicit to prevent implicit conversions.

pd1 is a raw pointer. MyPair p("tst", pd1); involves an implicit conversion to std::unique_ptr, which is why the compile fails in Clang and GCC, as it should be. You have to use an explicit conversion instead:

MyPair p("tst", datap_t(pd1));

A better option is to not use the raw pointer at all:

MyPair p("tst", std::make_unique<data_t>());

Clang and GCC are doing the right thing, Visual Studio is not (despite its unique_ptr documentation showing the relevant constructor is explicit).

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770