Re[33]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 06.07.23 16:22
Оценка:
Здравствуйте, so5team, Вы писали:

S>Вот этот вариант, вроде бы, работает вне зависимости от версии компилятора:


Супер! Благодарю.
Re[4]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 07.07.23 21:51
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>C++ компилируется сверху вниз. На момент компиляции определённой строки он знает только то, что было написано выше.


Если бы.
Re[33]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 09.07.23 03:58
Оценка:
Здравствуйте, so5team, Вы писали:

S>Вот этот вариант, вроде бы, работает вне зависимости от версии компилятора:


Вот, пытался понять суть все-таки, т.е. понять как там внутри unique_ptr устроена проверка и почему этой проверке важно отличать конструктор по умолчанию от пустого.

Такой код:

template <class _Ty>
struct default_delete2;

template <class _Ty, class _Dx = default_delete2<_Ty>>
class unique_ptr2;

template <class _Ty, class _Dx>
class unique_ptr2 {
};

template <class _Ty>
struct default_delete2 { // default deleter for unique_ptr
    constexpr default_delete2() noexcept = default;

    inline void operator()(_Ty* _Ptr) const noexcept
    {
        static_assert(0 < sizeof(_Ty), "can't delete an incomplete type");
        delete _Ptr;
    }
};


Это типа аналог урезанный unique_ptr — называется unique_ptr2. Но от него нужна только эта проверка.

По идее как-то должен вызываться оператор скобок () для default_delete (у нас default_delete2). Но где он вызывается — что-то я не увидел в коде.
Re[34]: Ошибка, если конструктор определен в h-файле (этюд?)
От: so5team https://stiffstream.com
Дата: 09.07.23 06:02
Оценка: -1
Здравствуйте, Shmj

"Один дурак может вдесятеро больше задать вопросов, чем десять мудрецов способны разрешить" (с)
Re[31]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 09.07.23 16:09
Оценка:
Здравствуйте, rg45, Вы писали:

R>Да пожалуйста (как же ты надоел):


Хотел еще узнать, знаете ли вы как оно внутри работает?

Там примерно такой код:

template <class _Ty>
struct default_delete2;

template <class _Ty, class _Dx = default_delete2<_Ty>>
class unique_ptr2;

template <class _Ty, class _Dx>
class unique_ptr2 {
};

template <class _Ty>
struct default_delete2 { // default deleter for unique_ptr
    constexpr default_delete2() noexcept = default;

    inline void operator()(_Ty* _Ptr) const noexcept
    {
        static_assert(0 < sizeof(_Ty), "can't delete an incomplete type");
        delete _Ptr;
    }
};


Срабатывает static_assert в операторе (). Но как-то не увидел где вызывается этот оператор — скобок, как сделать мин. функционал, который приведет к тому же эффекту?

Потратил кучу времени на GPT, может и сам бы нашел — уже сил нету. Последний пустил по кругу: https://chat.openai.com/share/f7643cf6-5c78-414d-958d-a5d2b7f88327
Re[35]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 09.07.23 16:10
Оценка:
Здравствуйте, so5team, Вы писали:

S>"Один дурак может вдесятеро больше задать вопросов, чем десять мудрецов способны разрешить" (с)


А что там реально сложно понять? Вы понимаете же как оно внутри работает и почему такой static_assert сработал? Или просто сталкивались на практике с этом не вникая в глубинную причину?
Re[32]: Ошибка, если конструктор определен в h-файле (этюд?)
От: rg45 СССР  
Дата: 09.07.23 16:36
Оценка:
Здравствуйте, Shmj, Вы писали:

S>
S>template <class _Ty>
S>struct default_delete2 { // default deleter for unique_ptr
S>    constexpr default_delete2() noexcept = default;

S>    inline void operator()(_Ty* _Ptr) const noexcept
S>    {
S>        static_assert(0 < sizeof(_Ty), "can't delete an incomplete type");
S>        delete _Ptr;
S>    }
S>};
S>


S>Срабатывает static_assert в операторе (). Но как-то не увидел где вызывается этот оператор — скобок, как сделать мин. функционал, который приведет к тому же эффекту?


Можно, конечно, чуть позже сделаем.

Вкратце: весь фокус здесь в том, в какой момент происходит инстанцирование класса делетера. А происходит оно при первом использовании — т.е. в точке инициализации умного указателя. А точка инициализации умного указателя находится в конструкторе класса (в нашем примере это был конструктор класса Class1). Когда конструктор определен в теле класса, в точке инстанцирования делетера определение класса Class1::Impl скрыто от компилятора и происходит ошибка компиляции (срабатывает static_assert). Когда же мы переносим конструктор в cpp, ситуация меняется — здесь уже видно определение класса Impl, и все компилируется успешно.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[32]: Ошибка, если конструктор определен в h-файле (этюд?)
От: rg45 СССР  
Дата: 09.07.23 16:57
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Хотел еще узнать, знаете ли вы как оно внутри работает?


Там все несложно: объект делетера передается параметром по умолчанию в конструктор умного указателя и сохраняется в объекте умного указателя. А потом этот делетер вызызывается в деструкторе умного указателя.

И тут есть один не очень очевидный, но важный момент, который нужно понимать. В зависимости от реализации, вызова делетера может и не произойти — в деструкторе класса умного указателя может находиться проверка — вызывать делетер только при условии, если указатель ненулевой. НО! Эта проверка происходит во время выполнения. А static_assert срабатывает во время компиляции. Улавливаешь момент? Произодет вызов делетера или нет, во время компиляции не известно, но компилятор видит, что существует по крайней мере одна веточка в ветвлении программы, когда делетер МОЖЕТ быть вызван. Поэтому компилятор вынужден инстанцировать функцию-член operator() делетера. Вот при этом инстанцировании и срабатывает static_assert. Понятно объяснил?
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 09.07.2023 17:08 rg45 . Предыдущая версия . Еще …
Отредактировано 09.07.2023 17:07 rg45 . Предыдущая версия .
Отредактировано 09.07.2023 17:06 rg45 . Предыдущая версия .
Re[32]: Ошибка, если конструктор определен в h-файле (этюд?)
От: rg45 СССР  
Дата: 09.07.23 18:42
Оценка: 12 (1)
Здравствуйте, Shmj, Вы писали:

S>Хотел еще узнать, знаете ли вы как оно внутри работает?

S>Срабатывает static_assert в операторе (). Но как-то не увидел где вызывается этот оператор — скобок, как сделать мин. функционал, который приведет к тому же эффекту?

Ну вот тебе эскиз реализации. Понятное дело, что все очень упрощенно, это лишь для понимания принципа, как оно там внутри устроено:

http://coliru.stacked-crooked.com/a/efb3907d3c848173
(Поправил: перенес static_assert из деструктора умного указателя в класс делетера)

#include <utility>

template <typename T>
struct MyDeleter
{
   void operator()(T* t) const
   {
       static_assert(sizeof(T), "Incomplete type");
       delete t;
   }
};

template <typename T, typename DeleterT = MyDeleter<T>>
class MySmartPtr
{
public:

   MySmartPtr() = default;
   explicit MySmartPtr(T* p, DeleterT deleter = {})
      : m_p(p), m_deleter(std::move(deleter)) {}

   T& operator * () const { assert(m_p); return *m_p; }
   T* operator -> () const { assert(m_p); return m_p; }
   explicit operator bool() const { return m_p != nullptr; }

   ~MySmartPtr()
   {
      if (m_p)
      {
         m_deleter(m_p);
      }
   }

private:
   T* m_p{};
   DeleterT m_deleter{};
};

class Class1
{
public:

   Class1(){}
   explicit Class1(int);
   ~Class1();

private:

   class Impl;

   MySmartPtr<Impl> m;
};

int main()
{
}


Как дополнить недостающие члены класса Class1 и поэкспериментировать с переносом конструктора, ты знаешь.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 10.07.2023 7:41 rg45 . Предыдущая версия .
Re[36]: Ошибка, если конструктор определен в h-файле (этюд?)
От: so5team https://stiffstream.com
Дата: 10.07.23 05:24
Оценка: +1
Здравствуйте, Shmj, Вы писали:

S>А что там реально сложно понять?


Нет.

S>Вы понимаете же как оно внутри работает и почему такой static_assert сработал?


Да.

S>Или просто сталкивались на практике с этом не вникая в глубинную причину?


Shmj, большинства ваших тупых вопросов не возникло бы, если бы вы взяли на себя труд погрузиться в C++ нормально. Например, проштудировали бы "Язык программирования C++" от Страуструпа и повыполняли бы упражнения, которые он дает в конце каждой главы.

Вместо этого вы пытаетесь воспользоваться помощью форумчан для того, чтобы вам задарма влили в голову знания, которые приобретаются самостоятельно (за счет учебы и практики). Закономерным итогом становится то, что "ваши рыжие кудри примелькаются, и вас просто начнут бить" (с) Но, поскольку дать вам по шее в прямом смысле не получится, остается высказывать вам свое "фи" доступными на форуме способами.

Почему этого еще не начал делать rg45 для меня загадка. Вот уж, поистине, святой человек.
Re[37]: Ошибка, если конструктор определен в h-файле (этюд?)
От: rg45 СССР  
Дата: 10.07.23 06:10
Оценка:
Здравствуйте, so5team, Вы писали:

S>Почему этого еще не начал делать rg45 для меня загадка. Вот уж, поистине, святой человек.


Мне показалось, что, в кои-то веки, он в чем-то пытается самостоятельно разобраться. Пускай даже подходя не совсем с нормальной стороны, но это были уже действительно вопросы по существу, а не вот эти его: "Я понял, есть два вида С++". Ну и на радостях у меня возникло желание помочь.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[12]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Dym On Россия  
Дата: 24.07.23 09:25
Оценка: -1
Здравствуйте, Shmj, Вы писали:

S>Вопрос то тянет на этюд

Этюд: Что имел в виду Shmj?

Не, тут только чатгпт сможет ответить
Счастье — это Glück!
Re[13]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 24.07.23 10:48
Оценка:
Здравствуйте, Dym On, Вы писали:

DO>Этюд: Что имел в виду Shmj?

DO>Не, тут только чатгпт сможет ответить

Уже давно все обсудили и ответили, всем кроме вас — вопрос был понятен.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.