Уникальный указатель в базовом классе запрещает создание экземпляров с ошибкой «попытка обратиться к удаленной функции» - PullRequest
4 голосов
/ 03 июля 2019

Я обновил свой набор инструментов C ++ из Visual Studio 2013 до Visual Studio 2017 / 2019.

Теперь у меня возникает ряд ошибок компиляции в виде:

<source>(13): error C2280: 'OfflineFixture::OfflineFixture(const OfflineFixture &)': attempting to reference a deleted function

<source>(8): note: compiler has generated 'OfflineFixture::OfflineFixture' here

<source>(8): note: 'OfflineFixture::OfflineFixture(const OfflineFixture &)': function was implicitly deleted because a data member invokes a deleted or inaccessible function 'std::unique_ptr<int,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)'

Уникальный указательявляется членом класса, который не имеет конструктора и деструктора.В этом случае Visual Studio позволяет создать экземпляр объекта следующим образом:

OfflineFixture a{};  // works!

Но использование:

auto&& a = OfflineFixture{};

дает указанную выше ошибку компиляции.

const auto& a = OfflineFixture{};

также даетвыше ошибка компиляции.

Пожалуйста, посмотрите здесь: https://gcc.godbolt.org/z/XtP40t

Мой вопрос: мой код неверен?

Данные примеры компилируютсяиспользуя: gcc (9.1 и ниже) clang Visual Studio 2013

Но он не работает:

  • Visual Studio 2015

  • Visual Studio 2017

  • Visual Studio 2019

Один из способов исправить это - реализовать конструктор по умолчанию в OfflineFixture.

Минимальный пример:

#include <memory>

struct OfflineFixture
{
    void x() const {} 
    int i;
    std::unique_ptr<int> m_calc;
};

int test() {

#if 1
    const auto&& a = OfflineFixture{};
#else
    OfflineFixture a{};
#endif
    a.x();

    return 0;
}

Ответы [ 3 ]

2 голосов
/ 03 июля 2019

Давайте сделаем некоторые предварительные замечания здесь.

В общем, утверждение:

const auto&& a = Foo{};

совершенно законно в C ++ .Более того, не верно, что это неопределенное поведение.Фактически, это прекрасный пример Инициализация ссылки с продлением срока действия временного.

Всякий раз, когда ссылка связана с временным или подобъектом, время жизнивременное расширение расширяется, чтобы соответствовать времени жизни ссылки [...].

Оно продолжается с некоторыми исключениями (я не буду их всех цитировать), но объявление нового объектане является частью этих исключений.


Что касается вашего класса, очевидно, проблема в том, что std::unique_ptr член.

Вот минимальный пример:

#include <memory>

struct OfflineFixture {
  std::unique_ptr<int> m_calc;
};

void test() {
  const auto&& a = OfflineFixture{};  // <--- Error in msvc
}

Каким-то образом MSVC пытается создать копию объекта.Действительно, ошибка связана с вызовом конструктора копирования (который удаляется из-за std::unique_ptr).

Поскольку здесь не нужно выполнять никаких копий, похоже, что это msvc ошибка.

Примечание: gcc и clang прекрасно с этим компилируются.

1 голос
/ 04 июля 2019

Интересно отметить, что MSVC показывает это ошибочное поведение, только если вы не предоставляете конструктор или если вы предоставляете конструктор по умолчанию:

struct OfflineFixture {
    OfflineFixture()=default;
    //...
};

Пример можно исправить, предоставив конструктору пустой блок:

struct OfflineFixture {
    OfflineFixture(){}
    //...
};

, который прекрасно компилируется.

1 голос
/ 03 июля 2019

Я добавил constructor и move constructor, как показано в приведенном ниже коде.

Это решает проблему.

struct OfflineFixture
{
    void x() const {} 
    int i;
    std::unique_ptr<int> m_calc;

    OfflineFixture(){}
    OfflineFixture(OfflineFixture &&){}

    //implicit
    OfflineFixture(const OfflineFixture&) = default;
    OfflineFixture& operator=(const OfflineFixture&) = default;
    ~OfflineFixture() = default;

 };

As, const auto&& a = OfflineFixture{}; требует constructor и move constructor

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...