Отсутствующий конструктор копирования в 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 . Предыдущая версия .
Re[3]: Отсутствующий конструктор копирования в MSVC2019 вызывает ош
От: andrey.desman  
Дата: 07.03.24 15:53
Оценка:
Здравствуйте, Marty, Вы писали:

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


У тебя же перемещение запрещено явно твоим NonCopiable.
Переместить он пытается, но тихо обламывается, потому что всегда можно скопировать если вдруг не прокатило. Далее пытается копировать, но и тут облом. Вот он и говорит, что скопировать не может.
Re: Отсутствующий конструктор копирования в MSVC2019 вызывает ош
От: andrey.desman  
Дата: 07.03.24 15:56
Оценка:
Здравствуйте, Marty, Вы писали:

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


Суть другая. Во время return работает copy elision, copy/move конструкторы не нужны. Обламывается он в момент передачи в make_shared. Как только ты воткнул return std::move, то обламывается уже в момент return.

Разреши мув конструктор, все будет работать.
Re[3]: Отсутствующий конструктор копирования в MSVC2019 вызы
От: rg45 СССР  
Дата: 07.03.24 16:38
Оценка: +3
Здравствуйте, Marty, Вы писали:

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>


Ну хорошо, а в IObject что? Ты в курсе, что, если ты объявил какой-то конструктор как default, это еще не гарантия того, что этот конструктор будет реально доступен? "default" на раз может реализоваться в "delete", если в классе присутствуют подобъекты(члены, базовые классы, члены базовых классов...) с явно или неявно удаленным конструктором.

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

Я бы предложил тебе поработать над минимизированным примером, воспроизводящем проблему, который можно было бы загрузить в какой-нибудь онлайн компилятор. И очень вероятно, что ошибку ты найдешь сам, в процессе работы над этим примером.
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 07.03.2024 16:48 rg45 . Предыдущая версия . Еще …
Отредактировано 07.03.2024 16:40 rg45 . Предыдущая версия .
Re: Отсутствующий конструктор копирования в MSVC2019 вызывает ош
От: rg45 СССР  
Дата: 07.03.24 16:43
Оценка:
Здравствуйте, Marty, Вы писали:

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


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


Ну у тебя и так здесь rvalue выражение, что ты рассчитываешь получить еще от move?
--
Справедливость выше закона. А человечность выше справедливости.
Re[4]: Отсутствующий конструктор копирования в MSVC2019 вызывает ош
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 07.03.24 17:03
Оценка:
Здравствуйте, andrey.desman, Вы писали:

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


AD>У тебя же перемещение запрещено явно твоим NonCopiable.

AD>Переместить он пытается, но тихо обламывается, потому что всегда можно скопировать если вдруг не прокатило. Далее пытается копировать, но и тут облом. Вот он и говорит, что скопировать не может.

Разве? Я думал, что = default говорит использовать ту версию, которую он сам сгенерил, не?
У меня в NonCopiable copy ctor/op= запрещены
Маньяк Робокряк колесит по городу
Re[2]: Отсутствующий конструктор копирования в MSVC2019 вызывает ош
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 07.03.24 17:04
Оценка:
Здравствуйте, andrey.desman, Вы писали:

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


AD>Суть другая. Во время return работает copy elision, copy/move конструкторы не нужны. Обламывается он в момент передачи в make_shared. Как только ты воткнул return std::move, то обламывается уже в момент return.


AD>Разреши мув конструктор, все будет работать.


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


R>Ну хорошо, а в IObject что? Ты в курсе, что, если ты объявил какой-то конструктор как default, это еще не гарантия того, что этот конструктор будет реально доступен? "default" на раз может реализоваться в "delete", если в классе присутствуют подобъекты(члены, базовые классы, члены базовых классов...) с явно или неявно удаленным конструктором.


R>Смотри, как получается, ты ждешь, что тебе помогут, не показывая всего кода. Так можно потратить уйму времени с нулевым результатом.


Сорян
struct IObject
{
    virtual ~IObject() {}

}; // struct IObject



R>Я бы предложил тебе поработать над минимизированным примером, воспроизводящем проблему, который можно было бы загрузить в какой-нибудь онлайн компилятор. И очень вероятно, что ошибку ты найдешь сам, в процессе работы над этим примером.



Ну, пока решилось, были ошибочные представления о реализации make_shared в MSVC2019, из-за чего я пошел не тем путём

А, вспомнил, почему так получилось. Был код с make_shared, который в MSVC2019 не собирался, а у коллеги в MSVC2022 собирался. Мы поковыряли, и решили, что что-то не так с make_shared в MSVC2019
Маньяк Робокряк колесит по городу
Re[2]: Отсутствующий конструктор копирования в MSVC2019 вызывает ош
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 07.03.24 17:11
Оценка: :)
Здравствуйте, rg45, Вы писали:

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


R>Ну у тебя и так здесь rvalue выражение, что ты рассчитываешь получить еще от move?


Я хотел сказать ему: "ну пожалуста-пожалуста, сделай мув"
Маньяк Робокряк колесит по городу
Re[4]: Отсутствующий конструктор копирования в MSVC2019 вызы
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 07.03.24 17:18
Оценка:
Здравствуйте, andrey.desman, Вы писали:


AD>А,просмотрел, что мув разрешен. Тогда да, что-то не мувается по умолчанию.


Понять бы, что. По всей иерархии наследования никаких полей в классах нет, только чисто виртуальные функции. Ни конструкторов, ни операторов= никакиех нет вообще, только в финальном классе есть конструктор.
А в финальном классе так:

struct WindowTimerImpl : public IWindowTimer
{

    HWND         hWnd           = 0;
    UINT_PTR     idTimerEvent   = 0;
    timeout_t    timerTimeoutMs = 0;
    bool         running        = false;

    WindowTimerImpl(HWND h, UINT_PTR id, timeout_t timeoutMs, bool bRunning) : hWnd(h), idTimerEvent(id), timerTimeoutMs(timeoutMs), running(bRunning)
    {
        if (running)
        {
            restart();
        }
    }

};



До этого конструктор был приватным, и был публичный метод create.
Маньяк Робокряк колесит по городу
Re[5]: Отсутствующий конструктор копирования в MSVC2019 вызы
От: rg45 СССР  
Дата: 07.03.24 17:25
Оценка:
Здравствуйте, Marty, Вы писали:


M>Ну, пока решилось, были ошибочные представления о реализации make_shared в MSVC2019, из-за чего я пошел не тем путём


M>А, вспомнил, почему так получилось. Был код с make_shared, который в MSVC2019 не собирался, а у коллеги в MSVC2022 собирался. Мы поковыряли, и решили, что что-то не так с make_shared в MSVC2019


Ну вообще, все, что приходит на вход std::make_shared форвардится в конструкторы объекта создаваемого класса. Конструкторы могут быть разные — копирования, перемещения, преобразования, с одним параметром и с несколькими. Если что-то работает не так, как ожидается, то я стараюсь все такие моменты доводить до полной ясности. Вот когда есть небольшой понятный примерчик, который и там и сям работает, а не работает только на каком-то определенном компиляторе или режиме, вот тогда тогда только можно говорить, что это баг компилятора. А так это просто предположение, а точная причина так и не выяснена пока.
--
Справедливость выше закона. А человечность выше справедливости.
Re[4]: Отсутствующий конструктор копирования в MSVC2019 вызывает ош
От: T4r4sB Россия  
Дата: 07.03.24 17:28
Оценка: +1
Здравствуйте, Teolog, Вы писали:

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

T>А почему он должен хотеть перемещать?

Потому что результат вызова функции это rvalue?
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[6]: Отсутствующий конструктор копирования в MSVC2019 вызы
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 07.03.24 17:53
Оценка:
Здравствуйте, rg45, Вы писали:

R>Вот когда есть небольшой понятный примерчик, который и там и сям работает, а не работает только на каком-то определенном компиляторе или режиме, вот тогда тогда только можно говорить, что это баг компилятора. А так это просто предположение, а точная причина так и не выяснена пока.


На MSVC не работает так же, как у меня

https://godbolt.org/z/ba4Pexz3j
Маньяк Робокряк колесит по городу
Re[7]: Отсутствующий конструктор копирования в MSVC2019 вызы
От: rg45 СССР  
Дата: 07.03.24 18:00
Оценка:
Здравствуйте, Marty, Вы писали:

R>>Вот когда есть небольшой понятный примерчик, который и там и сям работает, а не работает только на каком-то определенном компиляторе или режиме, вот тогда тогда только можно говорить, что это баг компилятора. А так это просто предположение, а точная причина так и не выяснена пока.


M>На MSVC не работает так же, как у меня

M>https://godbolt.org/z/ba4Pexz3j

А давай, попробуем совсем-совсем упростить?

http://coliru.stacked-crooked.com/a/007b9a0be18537d8

#include <memory>

struct A
{
    A() = default;
    A(A&&) = default;

    A(const A&) = delete;

    static A Create() {return {}; }
};

A makeA() { return {}; }

int main()
{
    const auto sp = std::make_shared<A>(A::Create());
}


Можешь попробовать компильнуть у себя? Если возникнет та же ошибка — тады ой — это однозначно проблема MSVC. Ну а если откомпилится успешно, тогда твое предположение ошибочно, так получается.
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 07.03.2024 18:02 rg45 . Предыдущая версия . Еще …
Отредактировано 07.03.2024 18:01 rg45 . Предыдущая версия .
Re[7]: Отсутствующий конструктор копирования в MSVC2019 вызы
От: andrey.desman  
Дата: 07.03.24 18:14
Оценка: +1 :)
Здравствуйте, Marty, Вы писали:

M>На MSVC не работает так же, как у меня


Потому что ты, негодяй, не сказал, что есть деструктор.


If no user-defined move constructors are provided for a class type, and all of the following is true:

there are no user-declared copy constructors;
there are no user-declared copy assignment operators;
there are no user-declared move assignment operators;
there is no user-declared destructor.

Then the compiler will declare a move constructor as a non-explicit inline public member of its class with the signature T::T(T&&).

Re[8]: Отсутствующий конструктор копирования в MSVC2019 вызы
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 07.03.24 18:24
Оценка:
Здравствуйте, rg45, Вы писали:


R>Можешь попробовать компильнуть у себя? Если возникнет та же ошибка — тады ой — это однозначно проблема MSVC. Ну а если откомпилится успешно, тогда твое предположение ошибочно, так получается.


Это собралось. Вопрос в том, что не так у меня в том коде, который не компилируется
Маньяк Робокряк колесит по городу
Re[8]: Отсутствующий конструктор копирования в MSVC2019 вызы
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 07.03.24 18:26
Оценка:
Здравствуйте, andrey.desman, Вы писали:

M>>На MSVC не работает так же, как у меня


AD>Потому что ты, негодяй, не сказал, что есть деструктор.


Виноват
И что делать, если деструктор есть? Кроме как явно описать конструктор/оп= перемещения?
Маньяк Робокряк колесит по городу
Re[9]: Отсутствующий конструктор копирования в MSVC2019 вызы
От: rg45 СССР  
Дата: 07.03.24 19:57
Оценка:
Здравствуйте, Marty, Вы писали:

R>>Можешь попробовать компильнуть у себя? Если возникнет та же ошибка — тады ой — это однозначно проблема MSVC. Ну а если откомпилится успешно, тогда твое предположение ошибочно, так получается.


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


Во-о-от! И я о том же. Я тебе прямо очень-очень советую пробовать минимизировать твой код. Причина обязательно найдется, уверяю тебя.
--
Справедливость выше закона. А человечность выше справедливости.
Re[9]: Отсутствующий конструктор копирования в MSVC2019 вызы
От: rg45 СССР  
Дата: 07.03.24 19:58
Оценка:
Здравствуйте, Marty, Вы писали:

M>Виноват

M>И что делать, если деструктор есть? Кроме как явно описать конструктор/оп= перемещения?

Да добавь просто определения-пустышки вместо "default".
--
Справедливость выше закона. А человечность выше справедливости.
Re[10]: Отсутствующий конструктор копирования в MSVC2019 вызы
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 07.03.24 20:01
Оценка:
Здравствуйте, rg45, Вы писали:

M>>Виноват

M>>И что делать, если деструктор есть? Кроме как явно описать конструктор/оп= перемещения?

R>Да добавь просто определения-пустышки вместо "default".


Что значит — пустышки?
Маньяк Робокряк колесит по городу
Re[8]: Отсутствующий конструктор копирования в MSVC2019 вызы
От: rg45 СССР  
Дата: 07.03.24 20:27
Оценка:
Здравствуйте, andrey.desman, Вы писали:

AD>Потому что ты, негодяй, не сказал, что есть деструктор.


AD>

AD>If no user-defined move constructors are provided for a class type, and all of the following is true:

AD> there are no user-declared copy constructors;
AD> there are no user-declared copy assignment operators;
AD> there are no user-declared move assignment operators;
AD> there is no user-declared destructor.

AD>Then the compiler will declare a move constructor as a non-explicit inline public member of its class with the signature T::T(T&&).


Да, но там внизу есть еще такая приписочка:

https://timsong-cpp.github.io/cppwp/n4861/class.copy.ctor#8

[ Note: When the move constructor is not implicitly declared or explicitly supplied, expressions that otherwise would have invoked the move constructor may instead invoke a copy constructor. — end note]


Так что наличие пользовательского деструктора в базовом классе не должно препятствовать генерации конструктора перемещения в производном классе. Конструктор же перемещения базового класса не объявляется удаленным, он просто не генерируется компилятором. При этом конструктор перемещения производного класса может спокойно воспользоваться конструктором копирования базового. Действительно похоже на баг MSVC, причем характерный для отдельной версии.
--
Справедливость выше закона. А человечность выше справедливости.
Re[11]: Отсутствующий конструктор копирования в MSVC2019 вызы
От: rg45 СССР  
Дата: 07.03.24 20:34
Оценка:
Здравствуйте, Marty, Вы писали:

R>>Да добавь просто определения-пустышки вместо "default".


M>Что значит — пустышки?


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

struct IObject
{
   IObject() = default;
   IObject(const IObject&) = default;
   IObject& operator = (const IObject&) = default;

   IObject(IObject&&){}
   IObject& operator = (IObject&&) { return *this; }

   virtual ~IObject() {}

}; // struct IObject


Если после этого проблема уйдет, то попробуй и конструктор и оператор перемещения просто объявить default.

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

R>Так что наличие пользовательского деструктора в базовом классе не должно препятствовать генерации конструктора перемещения в производном классе. Конструктор же перемещения базового класса не объявляется удаленным, он просто не генерируется компилятором. При этом конструктор перемещения производного класса может спокойно воспользоваться конструктором копирования базового. Действительно похоже на баг MSVC, причем характерный для отдельной версии.


У меня есть и в финальном классе деструктор.

И не очень понятно, чем наличие деструктора мешает перемещению, он же при этом не должен же использоваться
Маньяк Робокряк колесит по городу
Re[9]: Отсутствующий конструктор копирования в MSVC2019 вызы
От: andrey.desman  
Дата: 07.03.24 20:41
Оценка:
Здравствуйте, rg45, Вы писали:

R>Да, но там внизу есть еще такая приписочка:


R>

R>[ Note: When the move constructor is not implicitly declared or explicitly supplied, expressions that otherwise would have invoked the move constructor may instead invoke a copy constructor. — end note]


Это то, что у него и происходит — ругается, что не может скопировать.

R>Так что наличие пользовательского деструктора в базовом классе не должно препятствовать генерации конструктора перемещения в производном классе.


Деструктор в производном объявлен.

R>Конструктор же перемещения базового класса не объявляется удаленным, он просто не генерируется компилятором. При этом конструктор перемещения производного класса может спокойно воспользоваться конструктором копирования базового. Действительно похоже на баг MSVC, причем характерный для отдельной версии.


Да, но здесь не оно.
Re[12]: Отсутствующий конструктор копирования в MSVC2019 вызы
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 07.03.24 20:43
Оценка:
Здравствуйте, rg45, Вы писали:

M>>Что значит — пустышки?


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


Добавил не весь, только перемещение

R>
R>struct IObject
R>{
R>   IObject(IObject&&){}
R>   IObject& operator = (IObject&&) { return *this; }

R>}; // struct IObject
R>


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

Сделал = default — заработало


R>Если после этого проблема уйдет, то попробуй и конструктор и оператор перемещения просто объявить default.


R>Но это на правах костыля. По идее все должно и так работать. Похоже-таки на баг msvc.



Потом подумал, может ты таки имел в виду самый базовый класс, где один виртуальный деструктор объявлен. Объявил default весь набор. Убрал в финальном классе. Не прокатило.
Маньяк Робокряк колесит по городу
Re[9]: Отсутствующий конструктор копирования в MSVC2019 вызы
От: andrey.desman  
Дата: 07.03.24 20:44
Оценка:
Здравствуйте, Marty, Вы писали:

M>Виноват

M>И что делать, если деструктор есть? Кроме как явно описать конструктор/оп= перемещения?

Явно задекларировать его как default. Но вроде как у тебя все равно же явные телодвижения нужны на перемещение? Timer id переместить в новый объект, в старом занулить, не?
Re[10]: Отсутствующий конструктор копирования в MSVC2019 вызы
От: rg45 СССР  
Дата: 07.03.24 20:46
Оценка:
Здравствуйте, Marty, Вы писали:

M>И не очень понятно, чем наличие деструктора мешает перемещению, он же при этом не должен же использоваться


Ну, с какой целью генерацию конструктора перемещения поставили в зависимость деструктору, это мне сложно объяснить. Но, с другой стороны, блокировка генерации конструктора не означает запрета семантики перемещения. Должна быть возможность открыть конструктор перемещения, просто объявив его как default. И как показывает практика, на других компиляторах это работает. И даже на msvc, более поздних версий.
--
Справедливость выше закона. А человечность выше справедливости.
Re[10]: Отсутствующий конструктор копирования в MSVC2019 выз
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 07.03.24 20:47
Оценка:
Здравствуйте, andrey.desman, Вы писали:

M>>Виноват

M>>И что делать, если деструктор есть? Кроме как явно описать конструктор/оп= перемещения?

AD>Явно задекларировать его как default.


Так работает, да.


AD>Но вроде как у тебя все равно же явные телодвижения нужны на перемещение? Timer id переместить в новый объект, в старом занулить, не?


Точно, мой косяк

Кстати, а есть рекомендации ведущих собаководов, как правильно писать move ctor/move op=?


UPD
Написал так:
  Скрытый текст
struct WindowTimerImpl : public IWindowTimer
{

    HWND         hWnd           = 0;
    UINT_PTR     idTimerEvent   = 0;
    timeout_t    timerTimeoutMs = 0;
    bool         running        = false;


    //WindowTimerImpl(HWND h, UINT_PTR id) : hWnd(h), idTimerEvent(id) {}

    WindowTimerImpl(HWND h, UINT_PTR id, timeout_t timeoutMs, bool bRunning) : hWnd(h), idTimerEvent(id), timerTimeoutMs(timeoutMs), running(bRunning)
    {
        if (running)
        {
            restart();
        }
    }

    WindowTimerImpl(WindowTimerImpl&& other)
    : hWnd          (std::exchange(other.hWnd, (HWND)0))
    , idTimerEvent  (std::exchange(other.idTimerEvent, 0u))
    , timerTimeoutMs(std::exchange(other.timerTimeoutMs, 0u))
    , running       (std::exchange(other.running, false))
    {
    }

    WindowTimerImpl& operator=(WindowTimerImpl&& other)
    {
        hWnd           = std::exchange(other.hWnd, (HWND)0);
        idTimerEvent   = std::exchange(other.idTimerEvent, 0u);
        timerTimeoutMs = std::exchange(other.timerTimeoutMs, 0u);
        running        = std::exchange(other.running, false);
        return *this;
    }
};


Но, по идее, у меня есть значения по умолчанию, или как такая inplace инициализация называется? По идее, mctor = default и наличия такой инициализации должно хватать для генерации того, что мне пришлось ручками натоптать, не?
Маньяк Робокряк колесит по городу
Отредактировано 07.03.2024 21:09 Marty . Предыдущая версия . Еще …
Отредактировано 07.03.2024 20:59 Marty . Предыдущая версия .
Re[13]: Отсутствующий конструктор копирования в MSVC2019 выз
От: rg45 СССР  
Дата: 07.03.24 20:57
Оценка:
Здравствуйте, Marty, Вы писали:

M>Потом подумал, может ты таки имел в виду самый базовый класс, где один виртуальный деструктор объявлен. Объявил default весь набор. Убрал в финальном классе. Не прокатило.


Да похоже я просто запутался во фрагментах кода и что-то сказал невпопад.

Ну общий принцип такой — объявляешь деструктор — объяви и конструктор перемещения (возможно, как default).

Но нужно помнить, что объявление конструтора перемещения удаляет копирующие конструктор и присваивание. Именно объявляет как delete, а не просто препятствует их автоматической генерации.
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 07.03.2024 21:00 rg45 . Предыдущая версия .
Re[11]: Отсутствующий конструктор копирования в MSVC2019 выз
От: rg45 СССР  
Дата: 07.03.24 21:09
Оценка:
Здравствуйте, Marty, Вы писали:

M>Кстати, а есть рекомендации ведущих собаководов, как правильно писать move ctor/move op=?


Не знаю, как там собаководы, но лично я стараюсь проектировать так, чтоб минимизировать необходимость определять самому специальные функции-члены. Это для меня как один из критериев качества дизайна. При этом необходимо помнить зависимости между ними. Вот хорошая картинка на эту тему:

--
Справедливость выше закона. А человечность выше справедливости.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.