Отсутствующий конструктор копирования в MSVC2019 вызывает ош
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 07.03.24 12:52
Оценка:
Здравствуйте!

MSVC2019, С++17

Есть базовый класс, конструктор копирования запрещён.

Есть реализация

struct WindowTimerImpl : public WindowTimerBase
{
//...

    WindowTimerImpl(HWND h, UINT_PTR id, timeout_t timeoutMs) {}

    static
    WindowTimerImpl create(HWND h, UINT_PTR requestedId, timeout_t timeoutMs)
    {
        auto id = ::SetTimer(h, requestedId, timeoutMs, 0);

        if (id==0)
        {
            throw std::runtime_error("Failed to create WindowTimer");
        }

        return WindowTimerImpl(h, id, timeoutMs, true);
        // return std::move(WindowTimerImpl(h, id, timeoutMs, true)); // !!! move version
    }

//...
};


В классе окна есть функция создания
    virtual WindowTimer createTimer(timeout_t timeoutMs) const override
    {
        auto pSharedImpl = std::make_shared<WindowTimerImpl>(WindowTimerImpl::create(getHwnd(), curTimerId++, timeoutMs));

//...



Говорит, что "attempting to reference a deleted function"

Ошибка иницииируется в недрах std в _Construct_in_place при вызове forward:
  Скрытый текст
template <class _Ty, class... _Types>
_CONSTEXPR20_DYNALLOC void _Construct_in_place(_Ty& _Obj, _Types&&... _Args) noexcept(
    is_nothrow_constructible_v<_Ty, _Types...>) {
#ifdef __cpp_lib_constexpr_dynamic_alloc
    if (_STD is_constant_evaluated()) {
        _STD construct_at(_STD addressof(_Obj), _STD forward<_Types>(_Args)...);
    } else
#endif // __cpp_lib_constexpr_dynamic_alloc
    {
        ::new (_Voidify_iter(_STD addressof(_Obj))) _Ty(_STD forward<_Types>(_Args)...); // !!!
    }
}


Ладно, попробовал вернуть через std::move. Стало ругаться на строчку с ним, но суть осталась та же.

Видимо, я чего-то не понимаю. Не подскажете, что?
Маньяк Робокряк колесит по городу
Отредактировано 07.03.2024 12:53 Marty . Предыдущая версия .
Re: Отсутствующий конструктор копирования в MSVC2019 вызывает ош
От: reversecode google
Дата: 07.03.24 13:08
Оценка:
мне лень вникать
но поставь уже 2022 студию
или кланг
они дают более вразумительные ошибки
чем 2019 компилер, проваливаясь в недра самого стл

сам это делаю
Re: Отсутствующий конструктор копирования в MSVC2019 вызывает ош
От: so5team https://stiffstream.com
Дата: 07.03.24 13:09
Оценка: +1
Здравствуйте, Marty, Вы писали:

M>Здравствуйте!


M>MSVC2019, С++17


M>Есть базовый класс, конструктор копирования запрещён.


А что с конструктором перемещения в базовом классе?

Ну и как бы не видя базового класса это может превратиться в гадание по кофейной гуще.
Re[2]: Отсутствующий конструктор копирования в MSVC2019 вызывает ош
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 07.03.24 13:20
Оценка:
Здравствуйте, so5team, Вы писали:

M>>MSVC2019, С++17


M>>Есть базовый класс, конструктор копирования запрещён.


S>А что с конструктором перемещения в базовом классе?


S>Ну и как бы не видя базового класса это может превратиться в гадание по кофейной гуще.


struct NonCopiableObject : public IObject
{
    NonCopiableObject() = default;

    NonCopiableObject(const NonCopiableObject&) = delete;
    NonCopiableObject& operator=(const NonCopiableObject&) = delete;

    NonCopiableObject(NonCopiableObject&&) = default;
    NonCopiableObject& operator=(NonCopiableObject&&) = default;

}; // struct NonCopiableObject
Маньяк Робокряк колесит по городу
Re[3]: Отсутствующий конструктор копирования в MSVC2019 вызывает ош
От: so5team https://stiffstream.com
Дата: 07.03.24 13:42
Оценка:
Здравствуйте, Marty, Вы писали:

M>>>Есть базовый класс, конструктор копирования запрещён.


S>>А что с конструктором перемещения в базовом классе?


S>>Ну и как бы не видя базового класса это может превратиться в гадание по кофейной гуще.


M>
struct NonCopiableObject : public IObject
M>{
M>    NonCopiableObject() = default;

M>    NonCopiableObject(const NonCopiableObject&) = delete;
M>    NonCopiableObject& operator=(const NonCopiableObject&) = delete;

M>    NonCopiableObject(NonCopiableObject&&) = default;
M>    NonCopiableObject& operator=(NonCopiableObject&&) = default;

M>}; // struct NonCopiableObject

M>


Т.е. у вас было так:
struct WindowTimerImpl : public WindowTimerBase

и WindowTimerBase -- это просто синоним для NonCopiableObject?
Или WindowTimerBase все таки отдельный класс?

PS. А разве NonCopiable, а не NonCopyable?
Re[4]: Отсутствующий конструктор копирования в MSVC2019 вызывает ош
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 07.03.24 13:48
Оценка:
Здравствуйте, so5team, Вы писали:

S>Т.е. у вас было так:

S>
S>struct WindowTimerImpl : public WindowTimerBase
S>

S>и WindowTimerBase -- это просто синоним для NonCopiableObject?
S>Или WindowTimerBase все таки отдельный класс?


struct IWindowTimer : public NonCopiableObject
{

    virtual int compare(const IWindowTimer *pTimer) const = 0;

    virtual bool restart(timeout_t timeoutMs) = 0;

    virtual bool restart() = 0;

    virtual bool stop() = 0;

    virtual bool isStopped() const = 0;

    virtual timeout_t getTimeout() const = 0;

}; // struct IWindowTimer

struct WindowTimerImpl : public IWindowTimer
{
//...



S>PS. А разве NonCopiable, а не NonCopyable?



Ошибка, да
Маньяк Робокряк колесит по городу
Re: Отсутствующий конструктор копирования в MSVC2019 вызывает ош
От: andrey.desman  
Дата: 07.03.24 13:55
Оценка:
Здравствуйте, Marty, Вы писали:

M>В классе окна есть функция создания

M>
M>    virtual WindowTimer createTimer(timeout_t timeoutMs) const override
M>    {
M>        auto pSharedImpl = std::make_shared<WindowTimerImpl>(WindowTimerImpl::create(getHwnd(), curTimerId++, timeoutMs));

M>//...
M>


Тыж явно зовешь конструктор копирования/перемещения через make_shared.
Пусть WindowTimerImpl::create сама возвращает shared.
Re[2]: Отсутствующий конструктор копирования в MSVC2019 вызывает ош
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 07.03.24 14:20
Оценка:
Здравствуйте, andrey.desman, Вы писали:


AD>Тыж явно зовешь конструктор копирования/перемещения через make_shared.


Была надежда, что компилер разберётся
Есть варианты ему подсказать, что там не надо копировать, а перемещать? std::move?


AD>Пусть WindowTimerImpl::create сама возвращает shared.


А других вариантов нет?


В принципе, есть конечно вариант обойтись без create, а всё сделать в конструкторе, но тут есть нюанс — в версии std::make_shared, которая есть в MSVC2019, оно не понимает списка аргументов, чтобы его передать в соответствующий конструктор, так что тут всё равно при вызове std::make_shared либо явно указывать конструктор, либо пытаться передать список инициализации, и надеяться, что там унутре обойдётся без копирования как-нибудь.
Маньяк Робокряк колесит по городу
Re[3]: Отсутствующий конструктор копирования в MSVC2019 вызывает ош
От: night beast СССР  
Дата: 07.03.24 14:32
Оценка:
Здравствуйте, Marty, Вы писали:

struct NonCopiableObject : public IObject
M>{
M>    NonCopiableObject() = default;

M>    NonCopiableObject(const NonCopiableObject&) = delete;
M>    NonCopiableObject& operator=(const NonCopiableObject&) = delete;

M>    NonCopiableObject(NonCopiableObject&&) = default;
M>    NonCopiableObject& operator=(NonCopiableObject&&) = default;

M>}; // struct NonCopiableObject


а какой дефаулт у классов с удаленным копи-конструктором?
Re[4]: Отсутствующий конструктор копирования в MSVC2019 вызывает ош
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 07.03.24 14:36
Оценка:
Здравствуйте, night beast, Вы писали:

NB>а какой дефаулт у классов с удаленным копи-конструктором?


Я там описываю явно только конструкторы с параметрами
Маньяк Робокряк колесит по городу
Re: Отсутствующий конструктор копирования в MSVC2019 вызывает ош
От: Teolog  
Дата: 07.03.24 14:48
Оценка:
Функция create возвращает не указатель а экземпляр обьекта.
бедный make_shared которому это дали пытается найти у класса конструктор которому в качестве параметра надо передать экземпляр самого класса и не может.
Re[2]: Отсутствующий конструктор копирования в MSVC2019 вызывает ош
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 07.03.24 14:56
Оценка:
Здравствуйте, Teolog, Вы писали:

T>Функция create возвращает не указатель а экземпляр обьекта.

T>бедный make_shared которому это дали пытается найти у класса конструктор которому в качестве параметра надо передать экземпляр самого класса и не может.

template <class _Ty, class... _Types>
shared_ptr<_Ty> make_shared(_Types&&... _Args)


Почему он хочет копировать, а не перемещать?
Маньяк Робокряк колесит по городу
Re[3]: Отсутствующий конструктор копирования в MSVC2019 вызывает ош
От: Teolog  
Дата: 07.03.24 14:56
Оценка:
M>В принципе, есть конечно вариант обойтись без create, а всё сделать в конструкторе, но тут есть нюанс — в версии std::make_shared, которая есть в MSVC2019, оно не понимает списка аргументов

Вы точно уверены что список аргументов не подходил? Может конструктор был приватным?
Re[4]: Отсутствующий конструктор копирования в MSVC2019 вызывает ош
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 07.03.24 15:00
Оценка:
Здравствуйте, Teolog, Вы писали:


M>>В принципе, есть конечно вариант обойтись без create, а всё сделать в конструкторе, но тут есть нюанс — в версии std::make_shared, которая есть в MSVC2019, оно не понимает списка аргументов


T>Вы точно уверены что список аргументов не подходил? Может конструктор был приватным?


С коллегой в четыре глаза смотрели, но, возможно, оба облажались. Щас глянул на прототип make_shared — по идее, работать должно, да. Попробую проверить эту идею
Маньяк Робокряк колесит по городу
Re[3]: Отсутствующий конструктор копирования в MSVC2019 вызывает ош
От: Teolog  
Дата: 07.03.24 15:03
Оценка:
M>Почему он хочет копировать, а не перемещать?
А почему он должен хотеть перемещать?
Чтобы перемещение работало надо кучу условий соблюсти и специально пинать ногами.
Возвращать по значению некопируемый класс — это такое себе
Re[2]: Отсутствующий конструктор копирования в MSVC2019 вызывает ош
От: so5team https://stiffstream.com
Дата: 07.03.24 15:05
Оценка:
Здравствуйте, andrey.desman, Вы писали:

M>>В классе окна есть функция создания

M>>
M>>    virtual WindowTimer createTimer(timeout_t timeoutMs) const override
M>>    {
M>>        auto pSharedImpl = std::make_shared<WindowTimerImpl>(WindowTimerImpl::create(getHwnd(), curTimerId++, timeoutMs));

M>>//...
M>>


AD>Тыж явно зовешь конструктор копирования/перемещения через make_shared.


Боюсь, здесь не так все просто. Ведь create возвращает rvalue, соответственно, shared_ptr конструирует WindowTimerImpl через конструктор перемещения, а не копирования.

Вот дистиллированный пример, который показывает, что если в базовых классах с операторами/конструкторами перемещения все OK, то и с make_shared должно быть OK:

#include <memory>

struct base
{
    virtual ~base() = default;

    base() = default;

    base(const base &) = delete;
    base & operator=(const base &) = delete;

    base(base &&) = default;
    base & operator=(base &&) = default;
};

struct derived : public base
{
    int a_;
    int b_;

    derived(int a, int b) : a_{a}, b_{b} {}

    [[nodiscard]] static derived create(int a, int b)
    {
        return { a, b };
    }
};

int main()
{
    auto d = std::make_shared<derived>(derived::create(0, 1));
    return d->a_ + d->b_;
}


В режиме C++17 нормально компилируется и VS2022, и VS2019.

У меня была когда-то похожая проблема, но там в одном из базовых классов затесался член класса с задизейбленными операторами копирования/перемещения. Поэтому компилятор и для наследника их не мог вывести.

Полагаю, у ТС-а что-то похожее. Но уже в самом WindowTimerImpl.
Re[5]: Отсутствующий конструктор копирования в MSVC2019 вызывает ош
От: Teolog  
Дата: 07.03.24 15:05
Оценка:
M>С коллегой в четыре глаза смотрели, но, возможно, оба облажались. Щас глянул на прототип make_shared — по идее, работать должно, да. Попробую проверить эту идею

По коду глядя WindowTimerImpl конструктор с тремя параметрами а вызывается с 4. Может в таком-же стиле
Re[4]: Отсутствующий конструктор копирования в MSVC2019 вызывает ош
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 07.03.24 15:07
Оценка:
Здравствуйте, Teolog, Вы писали:

M>>Почему он хочет копировать, а не перемещать?

T>А почему он должен хотеть перемещать?
T>Чтобы перемещение работало надо кучу условий соблюсти и специально пинать ногами.
T>Возвращать по значению некопируемый класс — это такое себе

В общем, да, я облажался, std::make_shared нормально работает со списком параметров конструктора
Маньяк Робокряк колесит по городу
Re[6]: Отсутствующий конструктор копирования в MSVC2019 вызывает ош
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 07.03.24 15:10
Оценка:
Здравствуйте, Teolog, Вы писали:

M>>С коллегой в четыре глаза смотрели, но, возможно, оба облажались. Щас глянул на прототип make_shared — по идее, работать должно, да. Попробую проверить эту идею


T>По коду глядя WindowTimerImpl конструктор с тремя параметрами а вызывается с 4. Может в таком-же стиле



Мы с коллегой не в этот раз смотрели. Но, видимо, тогда что-то проглядели, и я в этот раз сразу решил, что проблема существует, и не стал использовать список параметров при вызове make_shared.

Облажался
Маньяк Робокряк колесит по городу
Re[3]: Отсутствующий конструктор копирования в MSVC2019 вызы
От: andrey.desman  
Дата: 07.03.24 15:48
Оценка:
Здравствуйте, so5team, Вы писали:

S>Полагаю, у ТС-а что-то похожее. Но уже в самом WindowTimerImpl.


Так у него же явно все запрещено. И копи, и мув.


....

А,просмотрел, что мув разрешен. Тогда да, что-то не мувается по умолчанию.
Отредактировано 07.03.2024 16:05 andrey.desman . Предыдущая версия .
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.