Создайте std::pair или std::map с неявным значением std::unique_ptr

Этот код работает в 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;
}

Но clang и gcc дают ошибку:

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*&)

Вот идея, которую стоит попробовать.

Тот факт, что я могу вызвать datap_t(pd1) и он компилируется, означает, что конструктор действителен, так почему же этот шаблон не находит подходящего соответствия?

Я хотел добавить пару ключ-значение на карту с помощью emplace, и именно поэтому я хотел иметь это неявное преобразование в первую очередь. Обратите внимание, что, как и в Visual Studio, неявное преобразование работает для большинства других типов, таких как std::string из "raw string".

Этот ответ выглядит актуальным, но он говорит об исправленной ошибке и очень стар.


person dashesy    schedule 24.06.2016    source источник
comment
Не используйте необработанные указатели. auto pd1 = std::make_unique<data_t>().   -  person kfsone    schedule 25.06.2016
comment
@kfsone Нет, при работе с внешними библиотеками C работа с необработанными указателями неизбежна. Кроме того, мне интересно посмотреть, почему это работает в Visual Studio, а не в clang, а не искать, как заставить это работать :)   -  person dashesy    schedule 25.06.2016


Ответы (1)


Конструктор std::unique_ptr, принимающий в качестве входных данных один необработанный указатель, помечен как explicit для предотвращения неявных преобразований.

pd1 — необработанный указатель. MyPair p("tst", pd1); включает неявное преобразование в std::unique_ptr, поэтому компиляция в Clang и GCC завершается неудачно, как и должно быть. Вместо этого вы должны использовать явное преобразование:

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

Лучшим вариантом является вообще не использовать необработанный указатель:

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

Clang и GCC поступают правильно, а Visual Studio — нет (несмотря на его unique_ptr документацию< /a> показывает, что соответствующий конструктор — explicit).

person Remy Lebeau    schedule 24.06.2016