std :: make_shared, std :: unique_ptr и конструкторы перемещения - PullRequest
12 голосов
/ 19 декабря 2011

Следующий код компилируется с помощью clang 3.0 / libc ++:

#include <memory>

class Foo
{
public:
    Foo()
        : mem_(new int(10))
    {
    }
    std::unique_ptr<int> mem_;
};

int main()
{
    auto foo = std::make_shared<Foo>();
    return 0;
}

Но это не так (std::string параметр добавлен):

#include <memory>
#include <string>

class Foo
{
public:
    Foo(const std::string& s)
        : mem_(new int(10))
    {
    }
    std::unique_ptr<int> mem_;
};

int main()
{
    auto foo = std::make_shared<Foo>("aaa");
    return 0;
}

Clang жалуется на использование удаленного конструктора. Для меня это не имеет смысла, поскольку std::make_shared не должен копировать экземпляр Foo, единственное, что вызовет вызов (удаленный) конструктор копирования std::unique_ptr.

Но, о чудо, как только я определю конструктор перемещения явно, он скомпилируется.

#include <memory>
#include <string>

class Foo
{
public:
    Foo(const std::string& s)
        : mem_(new int(10))
    {
    }
    Foo(Foo&& other)
        : mem_(std::move(other.mem_))
    {
    }
    std::unique_ptr<int> mem_;
};

int main()
{
    auto foo = std::make_shared<Foo>("aaa");
    return 0;
}

Теперь вопросы:

  1. Почему он компилируется в первом примере, а не во втором?
  2. Может ли std::make_shared копировать / перемещать объект при его создании?
  3. Почему добавление конструктора перемещения решает проблему? Я не помню, чтобы добавление конструктора не по умолчанию должно подавлять неявный конструктор перемещения.

РЕДАКТИРОВАТЬ: Проверено, и все примеры, как представляется, прекрасно компилируются с gcc 4.5.1 (через ideone.com), я подозреваю, что это ошибка clang / libc ++, но вопросы 2 и 3 все еще остаются Кроме того, я хотел бы знать, какой компилятор более «правильный».

1 Ответ

20 голосов
/ 19 декабря 2011

Почему он компилируется в первом примере, а не во втором?

Это ошибка libc ++.Сейчас я работаю над ее исправлением ...

Может ли std :: make_shared копировать / перемещать объект при его создании?

Нет, не знаюверьте, что можете.

Почему добавление конструктора перемещения решает проблему?Я не помню, чтобы добавление не стандартного конструктора должно подавлять неявный конструктор перемещения.

В используемой вами версии clang конструкторы неявного перемещения еще не реализованы.

Обновление

Исправлено: http://llvm.org/bugs/show_bug.cgi?id=11616

...