Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 05.07.23 05:45
Оценка:
Этюд это или нет, но такое неясное поведение, просто интересно почему.

Есть h-файл, в нем декларирован класс и пустой конструктор. Есть еще куча кода, который и вызывает проблему — это как бы и есть неизвестное. Упрощенно так:

test.h

class Class1
{
public:
    Class1();
};


В test.cpp — уже определение:

#include "test.h"

Class1::Class1()
{

}


Так все работает.

Если же перенести определение в h-файл, вот так:

class Class1
{
public:
    Class1(){}
};


(и убрать из cpp-файла, конечно) — то получаю ошибку: invalid application of 'sizeof' to an incomplete type 'namespace1::Class2'. Где Class2 — это другой класс, который как-то связан с Class1.

Вопрос мой вот в чем. Я думал что абсолютно без разницы в h-файле определение или нет — думал что это эквивалентно и во всех жизненных ситуациях проблемы не вызовет. И представить не мог, что если убрать из cpp-файла этот пустой конструктор и перенести в h-файл, то получим ошибку компиляции. Как же это возможно?

Можете ли вы привести код, который продемонстрирует такую проблему? Т.е. чтобы при переносе в h-файл пустой конструктор — возникала ошибка компиляции.
Re: Ошибка, если конструктор определен в h-файле (этюд?)
От: so5team https://stiffstream.com
Дата: 05.07.23 06:14
Оценка: 10 (2) +9 -1
Здравствуйте, Shmj

Слушайте, а вы точно программист? И пишете работающие программы хоть на каком-то языке программирования?

Ну просто сложно в это поверить с учетом непроходимой тупости того, что вы пишете.
Как иначе охарактеризовать ваш вопрос, в котором вы не удосужились (а скорее даже не подумали, что это нужно) привести минимальный пример, демонстрирующий актуальную проблему. В ваших псевдо-фрагментах нет ничего про Class2, но показывая только Class1 и сообщение об ошибке компилятора, связанной с Class2 (не Class1), вы просите вам что-то объяснить.



https://www.youtube.com/watch?v=N-8jkDqR58U
Re[2]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 05.07.23 06:18
Оценка: :)))
Здравствуйте, so5team, Вы писали:

S>Слушайте, а вы точно программист? И пишете работающие программы хоть на каком-то языке программирования?


Да какая тебе разница кто я? Причем тут переход на личности?

S>Ну просто сложно в это поверить с учетом непроходимой тупости того, что вы пишете.

S>Как иначе охарактеризовать ваш вопрос, в котором вы не удосужились (а скорее даже не подумали, что это нужно) привести минимальный пример, демонстрирующий актуальную проблему. В ваших псевдо-фрагментах нет ничего про Class2, но показывая только Class1 и сообщение об ошибке компилятора, связанной с Class2 (не Class1), вы просите вам что-то объяснить.

Потому что проблема не известна. Как раз и вопрос в том, что может вызывать такое поведение — хотя бы один вариант.
Re[3]: Ошибка, если конструктор определен в h-файле (этюд?)
От: kov_serg Россия  
Дата: 05.07.23 06:44
Оценка: +5
Здравствуйте, Shmj, Вы писали:

S>Как раз и вопрос в том, что может вызывать такое поведение — хотя бы один вариант.


Вы
Re: Ошибка, если конструктор определен в h-файле (этюд?)
От: Muxa  
Дата: 05.07.23 06:51
Оценка:
S>Можете ли вы привести код, который продемонстрирует такую проблему? Т.е. чтобы при переносе в h-файл пустой конструктор — возникала ошибка компиляции.

Всмысле? У тебя же уже есть пример кода, демонстрирующий проблему. Зачем тебе еще один?
Re[2]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 05.07.23 07:01
Оценка: -2
Здравствуйте, Muxa, Вы писали:

S>>Можете ли вы привести код, который продемонстрирует такую проблему? Т.е. чтобы при переносе в h-файл пустой конструктор — возникала ошибка компиляции.


M>Всмысле? У тебя же уже есть пример кода, демонстрирующий проблему. Зачем тебе еще один?


Это не пример, это проект с 300 тыс. строк кода. Просто так выцедить кусок оттуда и довести до минимально воспроизводимой проблемы — это пол дня работы (оплачивать не будут), по этому нету примера.

Хотелось бы в принципе понять как такое возможно.
Отредактировано 05.07.2023 7:33 Shmj . Предыдущая версия . Еще …
Отредактировано 05.07.2023 7:14 Shmj . Предыдущая версия .
Re[3]: Ошибка, если конструктор определен в h-файле (этюд?)
От: so5team https://stiffstream.com
Дата: 05.07.23 07:39
Оценка: 1 (1) +7
Здравствуйте, Shmj, Вы писали:

S>>Слушайте, а вы точно программист? И пишете работающие программы хоть на каком-то языке программирования?


S>Да какая тебе разница кто я?


Большая. Если подобный вопрос задает студент, то можно (и нужно) потратить время и объяснить с примером как хорошие вопросы должны задаваться.
Если же вы сеньор-помидор, но все еще не понимаете, как обращаться за помощью на публичный форум, то можно пожелать сменить профессию.

S>Причем тут переход на личности?


Потому что ваша личность засрала половину RSDN-а своей тупизной.

S>Потому что проблема не известна. Как раз и вопрос в том, что может вызывать такое поведение — хотя бы один вариант.


Еще раз, для совсем уж ограниченных: не зная ничего про Class2, про его взаимоотношения с Class1, толком вам не ответишь. Можно разве что гадать на кофейной гуще, но зачем это кому-то?

S>Это не пример, это проект с 300 тыс. строк кода. Просто так выцедить кусок оттуда и довести до минимально воспроизводимой проблемы — это пол дня работы (оплачивать не будут), по этому нету примера.


А RSDN-неры должны сделать для вас это бесплатно?
Re: Ошибка, если конструктор определен в h-файле (этюд?)
От: B0FEE664  
Дата: 05.07.23 07:46
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Можете ли вы привести код, который продемонстрирует такую проблему? Т.е. чтобы при переносе в h-файл пустой конструктор — возникала ошибка компиляции.

Да, могу.
И каждый день — без права на ошибку...
Re[4]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 05.07.23 08:01
Оценка: :)))
Здравствуйте, so5team, Вы писали:

S>Еще раз, для совсем уж ограниченных: не зная ничего про Class2, про его взаимоотношения с Class1, толком вам не ответишь. Можно разве что гадать на кофейной гуще, но зачем это кому-то?


Хотя бы один пример как такая ошибка может возникать и с чем это может быть связано.

Я думал что эти два куска кода эквивалентны — что может сломать перенос пустого конструктора в h-файл?
Re[2]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 05.07.23 08:02
Оценка: :))) :))) :))
Здравствуйте, B0FEE664, Вы писали:

S>>Можете ли вы привести код, который продемонстрирует такую проблему? Т.е. чтобы при переносе в h-файл пустой конструктор — возникала ошибка компиляции.

BFE>Да, могу.

Докажите.
Re[5]: Ошибка, если конструктор определен в h-файле (этюд?)
От: so5team https://stiffstream.com
Дата: 05.07.23 08:07
Оценка: +3
Здравствуйте, Shmj, Вы писали:

S>>Еще раз, для совсем уж ограниченных: не зная ничего про Class2, про его взаимоотношения с Class1, толком вам не ответишь. Можно разве что гадать на кофейной гуще, но зачем это кому-то?


S>Хотя бы один пример как такая ошибка может возникать и с чем это может быть связано.


Я бы рискнул предположить, что имеет место быть что-то вроде:
// .hpp-файл.
class Class2; // Предварительное объявление.

class Class1 {
  Class2 member_;
  ...
public:
  Class1() {}
  ...
};

// .cpp-файл.
class Class2 { ... }; // Полное определение.


Тогда компилятор при генерации конструктора Class1 споткнется о то, что он не знает, как по дефолту инициализировать Class1::member_.
Но, имхо, здесь должна быть другая диагностика. Так что предположу, что взаимоотношения Class1 и Class2 более своеобразные.

S>Я думал


Так, стоп. "Вы" и "думал" -- это несовместные вещи, не нужно врать и себе, и другим.
Re[6]: Ошибка, если конструктор определен в h-файле (этюд?)
От: night beast СССР  
Дата: 05.07.23 08:12
Оценка: +3
Здравствуйте, so5team, Вы писали:

S>Я бы рискнул предположить, что имеет место быть что-то вроде:

S>
S>// .hpp-файл.
S>class Class2; // Предварительное объявление.

S>class Class1 {
S>  Class2 member_;
S>  ...
S>public:
S>  Class1() {}
S>  ...
S>};

S>// .cpp-файл.
S>class Class2 { ... }; // Полное определение.
S>


нет, без указателей такое не работает.
больше похоже на использование внутри Class1 чего-то вроде unique_ptr<Class2>
Re[7]: Ошибка, если конструктор определен в h-файле (этюд?)
От: so5team https://stiffstream.com
Дата: 05.07.23 08:18
Оценка:
Здравствуйте, night beast, Вы писали:

NB>нет, без указателей такое не работает.


Вот и я о том же. Хотя, если экземпляры Class1 нигде кроме test.cpp явным образом не создаются (используются только ссылки/указатели на Class1), то почему бы и нет в каком-то из компиляторов (об этом ТС так же ничего не сказал).

NB>больше похоже на использование внутри Class1 чего-то вроде unique_ptr<Class2>


Может и так. Но обычно для проблем с этим нужно определять в .hpp-файле пустой деструктор. Так что
Re[6]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 05.07.23 09:02
Оценка: :))) :)
Здравствуйте, so5team, Вы писали:

S>Я бы рискнул предположить, что имеет место быть что-то вроде:

S>
S>// .hpp-файл.
S>class Class2; // Предварительное объявление.

S>class Class1 {
S>  Class2 member_;
S>  ...
S>public:
S>  Class1() {}
S>  ...
S>};

S>// .cpp-файл.
S>class Class2 { ... }; // Полное определение.
S>


S>Тогда компилятор при генерации конструктора Class1 споткнется о то, что он не знает, как по дефолту инициализировать Class1::member_.

S>Но, имхо, здесь должна быть другая диагностика. Так что предположу, что взаимоотношения Class1 и Class2 более своеобразные.

Вот это уже по делу, хотя и не оно, к сожалению Для вашего примера перенос определения конструктора в cpp-файл ничего не меняет.

В любом случае благодарю за попытку, видимо не все так просто.

S>>Я думал

S>Так, стоп. "Вы" и "думал" -- это несовместные вещи, не нужно врать и себе, и другим.

Пока вы не доказали что способны решить эту задачу.
Re[7]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 05.07.23 09:03
Оценка: :))) :)
Здравствуйте, night beast, Вы писали:

NB>нет, без указателей такое не работает.

NB>больше похоже на использование внутри Class1 чего-то вроде unique_ptr<Class2>

Совершенно верно — unique_ptr<Class2> внутри есть.
Re[7]: Ошибка, если конструктор определен в h-файле (этюд?)
От: so5team https://stiffstream.com
Дата: 05.07.23 09:08
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Пока вы не доказали что способны решить эту задачу.


Shame on me!
Re[8]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 05.07.23 09:09
Оценка:
Здравствуйте, so5team, Вы писали:

S>Вот и я о том же. Хотя, если экземпляры Class1 нигде кроме test.cpp явным образом не создаются (используются только ссылки/указатели на Class1), то почему бы и нет в каком-то из компиляторов (об этом ТС так же ничего не сказал).


clang++ MacOS.

NB>>больше похоже на использование внутри Class1 чего-то вроде unique_ptr<Class2>

S>Может и так. Но обычно для проблем с этим нужно определять в .hpp-файле пустой деструктор. Так что

Деструктор не трогал, он тоже присутствует. Естественно в h-файле только декларация.
Re[3]: Ошибка, если конструктор определен в h-файле (этюд?)
От: B0FEE664  
Дата: 05.07.23 09:58
Оценка: +1
Здравствуйте, Shmj, Вы писали:

S>>>Можете ли вы привести код, который продемонстрирует такую проблему? Т.е. чтобы при переносе в h-файл пустой конструктор — возникала ошибка компиляции.

BFE>>Да, могу.
S>Докажите.

Докажу при условии, что вы пообещаете никогда в своей жизни больше не создавать файл с именем test.h
И каждый день — без права на ошибку...
Re[4]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 05.07.23 10:26
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Докажу при условии, что вы пообещаете никогда в своей жизни больше не создавать файл с именем test.h


Подождем, может еще кто знает.
Re: Ошибка, если конструктор определен в h-файле (этюд?)
От: ArtDenis Россия  
Дата: 05.07.23 10:45
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Этюд это или нет, но такое неясное поведение, просто интересно почему.


Думаю, если ты даже не попытаешься максимально упросить код, который ещё воспроизводит проблему, а просто приведёшь полный текст ошибки, то найдутся те, кто догадается в чём проблема
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re[2]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 05.07.23 11:56
Оценка: -1 :)
Здравствуйте, ArtDenis, Вы писали:

AD>Думаю, если ты даже не попытаешься максимально упросить код, который ещё воспроизводит проблему, а просто приведёшь полный текст ошибки, то найдутся те, кто догадается в чём проблема


Текст ошибки: invalid application of 'sizeof' to an incomplete type 'namespace1::Class2'

Но мой вопрос в другом — не нужно именно такую же ошибку. Вообще почему может возникать — не все ли равно компилятору где определен ПУСТОЙ конструктор??? Любое доказательство что компилятору не все равно — меня устроит.
Re[5]: Ошибка, если конструктор определен в h-файле (этюд?)
От: serg_joker Украина  
Дата: 05.07.23 12:09
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Подождем, может еще кто знает.

Ну я знаю. Но тебе ничего доказывать не буду.
Re[3]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Videoman Россия https://hts.tv/
Дата: 05.07.23 13:06
Оценка: 1 (1) +1
Здравствуйте, Shmj, Вы писали:

S>Но мой вопрос в другом — не нужно именно такую же ошибку. Вообще почему может возникать — не все ли равно компилятору где определен ПУСТОЙ конструктор??? Любое доказательство что компилятору не все равно — меня устроит.


Ему естественно не всё равно. Пустой конструктор в месте своего объявления также создает пустые конструкторы вех членов класса. Может быть ситуация, когда в .h есть только декларация члена класса, но нет определения, а в .cpp определение уже есть полностью. Обычно таким свойством обладают шаблонные классы параметризуемые типами не требующими определения до момента конструирования. Например конструктор std::unique_ptr<> по умолчанию может потребовать delete-r (и соответственно определение класса, его деструктор в частности) в месте определения конструктора родителя.
Re[3]: Ошибка, если конструктор определен в h-файле (этюд?)
От: vsb Казахстан  
Дата: 05.07.23 13:17
Оценка: 1 (1) +1
Здравствуйте, Shmj, Вы писали:

S>Текст ошибки: invalid application of 'sizeof' to an incomplete type 'namespace1::Class2'


S>Но мой вопрос в другом — не нужно именно такую же ошибку. Вообще почему может возникать — не все ли равно компилятору где определен ПУСТОЙ конструктор??? Любое доказательство что компилятору не все равно — меня устроит.


C++ компилируется сверху вниз. На момент компиляции определённой строки он знает только то, что было написано выше. Поэтому — нет, не всё равно. В первом случае у тебя сначала идёт декларация — что есть такой-то конструктор, потом идёт ещё какой-то код (вероятно связанный с Class2), потом уже идёт реализация конструктора. И на момент компиляции этой реализации конструктора компилятор знает размер Class2. Во втором случае — это не так.

Помимо прочего: заголовочные файлы включаются в проект несколько раз (обычно). И если у тебя реализация метода в заголовочном файле, то компилятор будет её компилировать несколько раз. Само по себе это не ошибка, линкер всё разрулит, но это просто неправильная организация кода, увеличение времени компиляции. Единственная причина держать реализацию функции или метода в заголовочном файле это использование шаблонов.
Отредактировано 05.07.2023 13:18 vsb . Предыдущая версия .
Re[3]: Ошибка, если конструктор определен в h-файле (этюд?)
От: rg45 СССР  
Дата: 05.07.23 13:25
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Да какая тебе разница кто я? Причем тут переход на личности?


S>Потому что проблема не известна. Как раз и вопрос в том, что может вызывать такое поведение — хотя бы один вариант.


Просто возникают некоторые сомнения, в адекватности описания поведения. Особенно с учетом твоей личности
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[8]: Ошибка, если конструктор определен в h-файле (этюд?)
От: rg45 СССР  
Дата: 05.07.23 13:28
Оценка: +1
Здравствуйте, Shmj, Вы писали:

S>Совершенно верно — unique_ptr<Class2> внутри есть.


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

R>Ну и сколько еще подробностей придется из тебя вытащить, чтоб получить наконец полную картину?


Мне не нужно знать в чем проблема была именно в том частном случае.

Мне нужно понимание почему вообще перенос пустого конструктора в H-файл может приводить к ошибке компиляции — какая разница компилятору?
Re[4]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 05.07.23 13:36
Оценка: :)))
Здравствуйте, Videoman, Вы писали:

V>Ему естественно не всё равно. Пустой конструктор в месте своего объявления также создает пустые конструкторы вех членов класса. Может быть ситуация, когда в .h есть только декларация члена класса, но нет определения, а в .cpp определение уже есть полностью. Обычно таким свойством обладают шаблонные классы параметризуемые типами не требующими определения до момента конструирования. Например конструктор std::unique_ptr<> по умолчанию может потребовать delete-r (и соответственно определение класса, его деструктор в частности) в месте определения конструктора родителя.


Вот еще бы минимальный пример...
Re[7]: Ошибка, если конструктор определен в h-файле (этюд?)
От: rg45 СССР  
Дата: 05.07.23 13:38
Оценка: +1 :)
Здравствуйте, Shmj, Вы писали:

S>Пока вы не доказали что способны решить эту задачу.


Просто непревзойденная наглость.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[5]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Videoman Россия https://hts.tv/
Дата: 05.07.23 13:52
Оценка: +2
Здравствуйте, Shmj, Вы писали:

S>Вот еще бы минимальный пример...

// .h

class class1;

class class2 {

  class2();

  std::unique_ptr<class1> ptr;
}

// .cpp

#include "class1.h"

class2::class2()
{
}

Как-то так, но я не компилировал.
Re[4]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 05.07.23 13:55
Оценка:
Здравствуйте, Videoman, Вы писали:

V>Ему естественно не всё равно. Пустой конструктор в месте своего объявления также создает пустые конструкторы вех членов класса. Может быть ситуация, когда в .h есть только декларация члена класса, но нет определения, а в .cpp определение уже есть полностью. Обычно таким свойством обладают шаблонные классы параметризуемые типами не требующими определения до момента конструирования. Например конструктор std::unique_ptr<> по умолчанию может потребовать delete-r (и соответственно определение класса, его деструктор в частности) в месте определения конструктора родителя.


Гипотеза разумная. Но почему-то не работает:

Class1.h:

#include <memory>

class Class2;

class Class1
{
public:
    Class1();
private:
    std::unique_ptr<Class2> obj;
};


Class1.cpp
#include "Class1.h"

class Class2
{
};


Class1::Class1()
{

}


— по вашей гипотезе должно собираться, верно? Ведь раз взяло конструктор из файла Class1.cpp — то должно было бы увидеть и определение класса. Но не увидело — выдает ошибку.
Re[6]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 05.07.23 14:01
Оценка:
Здравствуйте, Videoman, Вы писали:

V>Как-то так, но я не компилировал.


Сделал так:

Class1.h
#include <memory>

class Class2;

class Class1
{
public:
    Class1();
private:
    std::unique_ptr<Class2> ptr;
};


Class1.cpp
#include "Class1.h"
#include "Class2.h"

Class1::Class1()
{
}


Class2.h
class Class2
{
};


— не компилируется. unique_ptr хочет заранее знать какой класс даже в этом случае, не смотря на то, что конструктор только декларирован — ему пофиг.
Re[6]: Ошибка, если конструктор определен в h-файле (этюд?)
От: so5team https://stiffstream.com
Дата: 05.07.23 14:11
Оценка:
Здравствуйте, Videoman, Вы писали:

V>
V>// .h

V>class class1;

V>class class2 {

V>  class2();

V>  std::unique_ptr<class1> ptr;
V>}

V>// .cpp

V>#include "class1.h"

V>class2::class2()
V>{
V>}
V>

V>Как-то так, но я не компилировал.

С дефолтным конструктором unique_ptr здесь проблем нет, т.к. там просто обнуление указателя на Class1, а для этого не нужно компилятору видеть полное определение Class1. Проблема должна быть с деструктором, т.к. там есть delete, а для работы delete нужно полное определение класса.

ЗЫ. Это ж классика PImpl-а, если мне склероз окончательно не изменил.

ЗЗЫ. У ТС-а, скорее всего, что-то такое:

// .h
class Class2;

class Class1 {
  std::unique_ptr<Class2> ptr_member_{new Class2{}};
  ...
public:
  Class1();
  ~Class1();
  ...
};

// .cpp
class Class2 {...}

Class1::Class1() {}
Class1::~Class1() {}


В этом случае, если не путаю, перенос конструктора Class1 из .cpp в .h и должен привести к ошибке компиляции.
Re[5]: Ошибка, если конструктор определен в h-файле (этюд?)
От: vsb Казахстан  
Дата: 05.07.23 14:16
Оценка: 4 (1)
Хотя у меня не получилось повторить ситуацию, в которой, как я думал, компилятор будет ругаться. Поэтому прошу знатоков прокомментировать.

template <typename T>
class MyPtr {
  T *ptr;

  public: 
  MyPtr() {
    ptr = new T();
  }
};

class Class2;

class Class1 {
  MyPtr<Class2> c2ptr;

  Class1() {}
};

class Class2 { };


Я ожидал, что на строчке Class1(), где вызывается конструктор MyPtr, в свою очередь вызывающий конструктор Class2() программа не скомпилируется, т.к. на момент компиляции этой строки компилятор ещё не увидел полное объявление Class2 и не знает, есть ли у него публичный конструктор.

Однако же: компилируется. При этом если добавить классу Class2 приватный конструктор, то не компилируется, причём ошибка ссылается вперёд, туда, куда вроде как компилятор ещё не успел дойти.

Извиняюсь за дезинформацию, моё понимание С++ в данном случае подвело и я не знаю, почему так происходит.
Отредактировано 05.07.2023 14:18 vsb . Предыдущая версия .
Re[7]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 05.07.23 14:22
Оценка:
Здравствуйте, so5t

S>В этом случае, если не путаю, перенос конструктора Class1 из .cpp в .h и должен привести к ошибке компиляции.


Даже ваш вариант не компилируется — без переноса конструктора — use of undefined type 'Class2'
Re[9]: Ошибка, если конструктор определен в h-файле (этюд?)
От: B0FEE664  
Дата: 05.07.23 14:25
Оценка: +2
Здравствуйте, rg45, Вы писали:

R>Ну и сколько еще подробностей придется из тебя вытащить, чтоб получить наконец полную картину?


rg45, зачем полная картина? И так же всё ясно: раз речь про конструктор, значит не удаётся создать поля класса. Значит в Class1 есть указатель (или иное использование) на Class2. А в Class2 есть указатель или иное использование Class1 — это не обязательно, но весьма вероятно. Поэтому перед/в Class1 есть фраза class Class2; — чтобы разорвать циклическую зависимость. Это означает что в Class1 Class2 не полный и когда конструктор пытаются определить прямо в Class1, то компилятор ругается, что не может создать то, что не описано. Более того, зная что Shmj новичок в С++, то можно утверждать с большой долей вероятности, что он не знает про циклические зависимости классов и способов их разрешения. Не знает про случаи, когда inline методы определяются вне класса и обычно в отдельном файле (а в некоторых случаях ещё и со своим расширением типа *.inc или *.inl (Ещё вариант — это добавление include после определение класса, но такое — экзотика)). Короче, ничего необычного, кроме сообщения об ошибке. Вот она меня удивила, так как не знал про static_assert(sizeof(_Tp)>0, в unique_ptr. Думал про массив нулевого размера. Видать этот static_assert нужен для предотвращения проблемы некорректного вызова деструктора для pimpl идиомы, но я этого не проверял.
И каждый день — без права на ошибку...
Re[10]: Ошибка, если конструктор определен в h-файле (этюд?)
От: rg45 СССР  
Дата: 05.07.23 15:01
Оценка: +1
Здравствуйте, B0FEE664, Вы писали:

BFE>rg45, зачем полная картина? И так же всё ясно: раз речь про конструктор, значит не удаётся создать поля класса. Значит в Class1 есть указатель (или иное использование) на Class2. А в Class2 есть указатель или иное использование Class1 — это не обязательно, но весьма вероятно. Поэтому перед/в Class1 есть фраза class Class2; — чтобы разорвать циклическую зависимость. Это означает что в Class1 Class2 не полный и когда конструктор пытаются определить прямо в Class1, то компилятор ругается, что не может создать то, что не описано. Более того, зная что Shmj новичок в С++, то можно утверждать с большой долей вероятности, что он не знает про циклические зависимости классов и способов их разрешения. Не знает про случаи, когда inline методы определяются вне класса и обычно в отдельном файле (а в некоторых случаях ещё и со своим расширением типа *.inc или *.inl (Ещё вариант — это добавление include после определение класса, но такое — экзотика)). Короче, ничего необычного, кроме сообщения об ошибке. Вот она меня удивила, так как не знал про static_assert(sizeof(_Tp)>0, в unique_ptr. Думал про массив нулевого размера. Видать этот static_assert нужен для предотвращения проблемы некорректного вызова деструктора для pimpl идиомы, но я этого не проверял.


Объяснение выглядит очень убедительным. Но я, признаться, даже не пытался вникать в суть "задачи", принимая во внимание персону и стиль задания вопросов.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[6]: Ошибка, если конструктор определен в h-файле (этюд?)
От: andrey.desman  
Дата: 05.07.23 16:19
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>Я ожидал, что на строчке Class1(), где вызывается конструктор MyPtr, в свою очередь вызывающий конструктор Class2() программа не скомпилируется, т.к. на момент компиляции этой строки компилятор ещё не увидел полное объявление Class2 и не знает, есть ли у него публичный конструктор.

vsb>Однако же: компилируется. При этом если добавить классу Class2 приватный конструктор, то не компилируется, причём ошибка ссылается вперёд, туда, куда вроде как компилятор ещё не успел дойти.
vsb>Извиняюсь за дезинформацию, моё понимание С++ в данном случае подвело и я не знаю, почему так происходит.

Как минимум

https://timsong-cpp.github.io/cppwp/n4659/temp.dep.res#temp.point-8

A specialization for a function template, a member function template, or of a member function or static data member of a class template may have multiple points of instantiations within a translation unit, and in addition to the points of instantiation described above, for any such specialization that has a point of instantiation within the translation unit, the end of the translation unit is also considered a point of instantiation.


А там для зависимых имен кандидаты берутся из пространств имен, связанных с instantiation context.
Re[11]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 05.07.23 18:22
Оценка: :))) :))) :)))
Здравствуйте, rg45, Вы писали:

R>Объяснение выглядит очень убедительным. Но я, признаться, даже не пытался вникать в суть "задачи", принимая во внимание персону и стиль задания вопросов.


А вот оно видите как — нужно смотреть на суть.

Вопрос то тянет на этюд — никто из "знатоков" так и не смог ответить. Возможно придется мне на выходных найти время и таки выцедить минимальный пример (надеюсь что нет).
Re[12]: Ошибка, если конструктор определен в h-файле (этюд?)
От: rg45 СССР  
Дата: 05.07.23 18:25
Оценка: +3 :)
Здравствуйте, Shmj, Вы писали:

S>А вот оно видите как — нужно смотреть на суть.


На твою суть я тут уже насмотрелся предостаточно.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[12]: Ошибка, если конструктор определен в h-файле (этюд?)
От: T4r4sB Россия  
Дата: 05.07.23 18:46
Оценка: +10 :))) :)))
Здравствуйте, Shmj, Вы писали:

S>Вопрос то тянет на этюд — никто из "знатоков" так и не смог ответить.


Я знаю ещё более продвинутый вопрос, который тянет на этюд и на который никто не ответит.
  Скрытый текст
У меня проект не собирается, почему? Подробности не скажу.
Re[5]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Teolog  
Дата: 05.07.23 19:33
Оценка: +1
S>Я думал что эти два куска кода эквивалентны — что может сломать перенос пустого конструктора в h-файл?
Да — они эквивалентны, и причем здесь это?
какая буква в словосочетании "incomplete type" не ясна?
заголовок с типом class2 добавлен в .cpp но не в .h, либо не добавлен но имеет с ним циклическую зависимость
Так будет с каждым кто не понимает зачем c++ разделяет определения и имплементации.
Re[6]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 05.07.23 19:38
Оценка: :)
Здравствуйте, Teolog, Вы писали:

T>Да — они эквивалентны, и причем здесь это?

T>какая буква в словосочетании "incomplete type" не ясна?
T>заголовок с типом class2 добавлен в .cpp но не в .h, либо не добавлен но имеет с ним циклическую зависимость
T>Так будет с каждым кто не понимает зачем c++ разделяет определения и имплементации.

А теперь закрепите это примером, который демонстрирует данное поведение.
Re[7]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Videoman Россия https://hts.tv/
Дата: 05.07.23 21:01
Оценка: 6 (1)
Здравствуйте, Shmj, Вы писали:

S>- не компилируется. unique_ptr хочет заранее знать какой класс даже в этом случае, не смотря на то, что конструктор только декларирован — ему пофиг.


Потому что дело не только в конструкторе, но и в деструкторе. std::unique_ptr<Class2> деструктор для неполного объекта также не может создать. С деструктором Class1 проделай тоже самое:
сlass Class2;

class Class1
{
public:
    Class1();
    ~Class1();
private:
    std::unique_ptr<Class2> ptr;
};

//... тут все тоже самое
Re[8]: Ошибка, если конструктор определен в h-файле (этюд?)
От: PM  
Дата: 05.07.23 21:51
Оценка:
Здравствуйте, Videoman, Вы писали:

S>>- не компилируется. unique_ptr хочет заранее знать какой класс даже в этом случае, не смотря на то, что конструктор только декларирован — ему пофиг.


V>Потому что дело не только в конструкторе, но и в деструкторе. std::unique_ptr<Class2> деструктор для неполного объекта также не может создать. С деструктором Class1 проделай тоже самое:


Емнип, у Visual C++ была похожее поведение — если не объявлять деструктор явно, то генерировалась inline версия:
// test.hpp
сlass Class2;

class Class1 {
    std::unique_ptr<Class2> ptr;
    // нет явного ~Class1(), так что компилятор создает inline версию
    // в которой пытается вызывать деструктор Class2 
};


Мне лень искать подтверждение, насколько это соответсвует стандарту.

Исправление — объявить деструктор в классе, определить в реализации:
// test.hpp
сlass Class2;

class Class1 {
    std::unique_ptr<Class2> ptr;
    ~Class1();
};


// test.cpp
#include "test.hpp"

class Class2 {}; // полное определение нужно в любом случае

Class1::~Class1() = default; // достаточно сгенерированной версии, главное чтобы Class2 был здесь доступен
Re[13]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 06.07.23 04:15
Оценка: :))) :))) :))) :)
Здравствуйте, rg45, Вы писали:

S>>А вот оно видите как — нужно смотреть на суть.

R>На твою суть я тут уже насмотрелся предостаточно.

Ты зацикливаешься на человеке. Как видишь — это глупо, т.к. человек всего лишь сосуд — он наполняется разной инфой и его содержимое постоянно изменяется.

Уже много месяцев на форуме не было достойного вопроса. И вот, наконец, такой вопрос появился.
Re[7]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 06.07.23 04:52
Оценка:
Здравствуйте, so5team, Вы писали:

S>В этом случае, если не путаю, перенос конструктора Class1 из .cpp в .h и должен привести к ошибке компиляции.


Проверил с clang++ на MacOS

/Users/test/Desktop/cmake_test/Class1.h:6:43: error: allocation of incomplete type 'Class2'
std::unique_ptr<Class2> ptr_member_{new Class2{}};
^~~~~~
/Users/test/Desktop/cmake_test/Class1.h:3:7: note: forward declaration of 'Class2'
class Class2;
^
1 error generated.
make[2]: *** [CMakeFiles/main.dir/main.cpp.o] Error 1


— это ваш код оригинальный, который должен работать...
Re[8]: Ошибка, если конструктор определен в h-файле (этюд?)
От: so5team https://stiffstream.com
Дата: 06.07.23 05:16
Оценка:
Здравствуйте, Shmj, Вы писали:

S>- это ваш код оригинальный, который должен работать...


Кто должен, кому должен?

Интеллектуальный вы наш, перечитайте, пожалуйста, написанное мной и найдите хоть одно утверждение "должен".
Re[12]: Ошибка, если конструктор определен в h-файле (этюд?)
От: so5team https://stiffstream.com
Дата: 06.07.23 05:19
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Вопрос то тянет на этюд — никто из "знатоков" так и не смог ответить.


Какой же вы молодец, уели целый форум! Так нам и надо!

S>Возможно придется мне на выходных найти время и таки выцедить минимальный пример (надеюсь что нет).


Страшно представить, на какие лишения вы вынуждены будете пойти, чтобы уговорить RSDN дать ответ на ваш вопрос...
Re[9]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 06.07.23 05:25
Оценка:
Здравствуйте, PM, Вы писали:

PM>Исправление — объявить деструктор в классе, определить в реализации:


error: invalid application of 'sizeof' to an incomplete type 'Class2'
static_assert(sizeof(_Tp) > 0,
^~~~~~~~~~~


Это в вашем оригинальном коде — с конструктором по умолчанию. А по условию задачи должно компилироваться и ломаться если конструктор явно реализовать в H-файле.
Re[8]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 06.07.23 05:48
Оценка:
Здравствуйте, Videoman, Вы писали:

V>Потому что дело не только в конструкторе, но и в деструкторе. std::unique_ptr<Class2> деструктор для неполного объекта также не может создать. С деструктором Class1 проделай тоже самое:

V>
V>сlass Class2;

V>class Class1
V>{
V>public:
V>    Class1();
V>    ~Class1();
V>private:
V>    std::unique_ptr<Class2> ptr;
V>};

V>//... тут все тоже самое
V>


В принципе это уже близко.

Но у меня смотрите какой кейс был. Был класс с конструктором по умолчанию. Я быстро для тестов хотел добавить конструктор с параметром. Естественно этот конструктор с параметром потребовал явной реализации конструктора без параметра (пустого), чтобы старый код не отвалился. Добавил по быстрому в h-файл этот конструктор без параметров — и оно перестало компилироваться. Т.е. если конструктора нет вообще (используется по умолчанию все) — компилируется. Если добавить пустой конструктор в CPP-файле — тоже компилируется. А вот в H-файле не компилируется.

Т.е. разница:

1. Должно компилироваться, если конструктор не декларирован явно (т.е. когда по умолчанию). У вас — не компилируется если не определен явно.
2. Должно компилироваться, если в H-файле декларация а в CPP-определение (реализация). Тут ОК — ваш кейс совпадает.
3. Должно перестать компилироваться, если в H-файле определение (реализация). Тут ОК — ваш кейс тоже совпадает.

Хотелось бы еще 1 кейс чтобы тоже совпадал.
Re[14]: Ошибка, если конструктор определен в h-файле (этюд?)
От: rg45 СССР  
Дата: 06.07.23 06:02
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Уже много месяцев на форуме не было достойного вопроса. И вот, наконец, такой вопрос появился.


Это только для тебя, неуча, это достойный вопрос. Ты сейчас похож на маленького мальчика, который "открыл", что девочки устроены не так, как мальчики и с радостным криком прибежал удивить бабушку.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 06.07.2023 6:04 rg45 . Предыдущая версия .
Re[15]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 06.07.23 06:09
Оценка:
Здравствуйте, rg45, Вы писали:

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


Я понимаю что для вашего самолюбия такой вариант был бы идеален. Как бы раздуть свое эго за счет других.

Однако же в таком случае — вопрос бы получил ответ. Пока ответа полноценного нет.
Re[16]: Ошибка, если конструктор определен в h-файле (этюд?)
От: so5team https://stiffstream.com
Дата: 06.07.23 06:12
Оценка: +4
Здравствуйте, Shmj, Вы писали:

S>Однако же в таком случае — вопрос бы получил ответ. Пока ответа полноценного нет.


В эту игру можно играть вдвоем: пока полноценного вопроса нет.
Re[16]: Ошибка, если конструктор определен в h-файле (этюд?)
От: rg45 СССР  
Дата: 06.07.23 06:15
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Однако же в таком случае — вопрос бы получил ответ. Пока ответа полноценного нет.


Ты меня на "слабо" решил пробить, что ли? Ну хорошо, что будет, если я приведу такой пример? Избавишь этот форум от своего присутствия?
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[17]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 06.07.23 06:16
Оценка: :))) :))
Здравствуйте, rg45, Вы писали:

R>Ты меня на "слабо" решил пробить, что ли? Ну хорошо, что будет, если я приведу такой пример? Избавишь этот форум от своего присутствия?


Вы спасете честь форума.
Re[18]: Ошибка, если конструктор определен в h-файле (этюд?)
От: rg45 СССР  
Дата: 06.07.23 06:18
Оценка:
Здравствуйте, Shmj, Вы писали:

R>>Ты меня на "слабо" решил пробить, что ли? Ну хорошо, что будет, если я приведу такой пример? Избавишь этот форум от своего присутствия?


S>Вы спасете честь форума.


А, зассал, маленький Ну вот сиди и помалкивай, значит.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[17]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 06.07.23 06:23
Оценка:
Здравствуйте, so5team, Вы писали:

S>В эту игру можно играть вдвоем: пока полноценного вопроса нет.


Кратко так:

Есть класс, который имеет декларацию в H-файле и реализацию в CPP-файле. Этот класс имеет конструктор по умолчанию (т.е. явно конструктор не объявлен и не определен). Сделайте так, чтобы при добавлении явного пустого конструктора в декларацию класса, типа такого:

MyClass(){}


— код перестал компилироваться. При этом если этот же пустой конструктор лишь декларировать в H-файле а определить в CPP-файле — то код снова должен компилироваться (иначе было бы слишком просто).
Re[18]: Ошибка, если конструктор определен в h-файле (этюд?)
От: rg45 СССР  
Дата: 06.07.23 06:26
Оценка:
Здравствуйте, Shmj, Вы писали:


S>Есть класс, который имеет декларацию в H-файле и реализацию в CPP-файле. Этот класс имеет конструктор по умолчанию (т.е. явно конструктор не объявлен и не определен). Сделайте так, чтобы при добавлении явного пустого конструктора в декларацию класса, типа такого:


S>
S>MyClass(){}
S>


S> — код перестал компилироваться. При этом если этот же пустой конструктор лишь декларировать в H-файле а определить в CPP-файле — то код снова должен компилироваться (иначе было бы слишком просто).


Придурок, это классическая проблема, с которой сталкивался каждый, кто использует идиoму скрытой реализации (PImpl). Это только для тебя это является открытием.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 06.07.2023 6:27 rg45 . Предыдущая версия .
Re[19]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 06.07.23 06:33
Оценка:
Здравствуйте, rg45, Вы писали:

R>Придурок, это классическая проблема, с которой сталкивался каждый, кто использует идиoму скрытой реализации (PImpl). Это только для тебя это является открытием.




Попробуйте сделать и обломитесь.
Re[20]: Ошибка, если конструктор определен в h-файле (этюд?)
От: rg45 СССР  
Дата: 06.07.23 06:47
Оценка: -1
Здравствуйте, Shmj, Вы писали:

S>Попробуйте сделать и обломитесь.


Сто раз пробовал — ни разу не обломался. Я ж не ты, я не имею привычки словоблудить.

P.S. Мое предложение
Автор: rg45
Дата: 06.07.23
в силе если что. Трепло ссыкливое.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 06.07.2023 6:54 rg45 . Предыдущая версия . Еще …
Отредактировано 06.07.2023 6:52 rg45 . Предыдущая версия .
Отредактировано 06.07.2023 6:52 rg45 . Предыдущая версия .
Re[21]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 06.07.23 07:09
Оценка: :)))
Здравствуйте, rg45, Вы писали:

R>Сто раз пробовал — ни разу не обломался. Я ж не ты, я не имею привычки словоблудить.


Кроме меня есть еще несколько человек тут, кому было бы полезно — кто не знает ответа. Так что не нужно выставлять меня дураком.

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

А так возможно что попробовали и поняли что ваш вариант не работает, но признаваться стыдно и как бы хотите уйти в фактор личности.
Re[22]: Ошибка, если конструктор определен в h-файле (этюд?)
От: rg45 СССР  
Дата: 06.07.23 07:14
Оценка: -1
Здравствуйте, Shmj, Вы писали:

S>А так возможно что попробовали и поняли что ваш вариант не работает, но признаваться стыдно и как бы хотите уйти в фактор личности.


Если ты уверен, что мой вариант не работает, почему бы тебе не согласиться на пари
Автор: rg45
Дата: 06.07.23
?

А ответ прост, на самом деле — протому что ты — ссылкивое трепло.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[23]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 06.07.23 07:30
Оценка:
Здравствуйте, rg45, Вы писали:

R>Если ты уверен, что мой вариант не работает, почему бы тебе не согласиться на пари
Автор: rg45
Дата: 06.07.23
?

R>А ответ прост, на самом деле — протому что ты — ссылкивое трепло.

Мне предлагали менее жестокие условия — всего то не называть файлы словом test.h.

Не согласен, потому что вопрос касается теории и ответ нужен всем нам просто из любопытства и любознательности. Никакую реальную проблему этот ответ не решит, т.к. в проекте я просто перенес реализацию конструктора в CPP-файл.
Re[24]: Ошибка, если конструктор определен в h-файле (этюд?)
От: rg45 СССР  
Дата: 06.07.23 07:42
Оценка:
Здравствуйте, Shmj, Вы писали:

R>>Если ты уверен, что мой вариант не работает, почему бы тебе не согласиться на пари
Автор: rg45
Дата: 06.07.23
?

R>>А ответ прост, на самом деле — протому что ты — ссылкивое трепло.

S>Мне предлагали менее жестокие условия — всего то не называть файлы словом test.h.


А какое значение для тебя имеет жесткость условий? Ты же УВЕРЕН, что мой вариант не работает? Уверен?
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[25]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 06.07.23 07:54
Оценка: :))
Здравствуйте, rg45, Вы писали:

R>А какое значение для тебя имеет жесткость условий? Ты же УВЕРЕН, что мой вариант не работает? Уверен?


Умный всегда сомневается ,а дурак всегда уверен.

Я сомневаюсь что у тебя есть рабочее решение.
Re[18]: Ошибка, если конструктор определен в h-файле (этюд?)
От: so5team https://stiffstream.com
Дата: 06.07.23 07:55
Оценка: +2
Здравствуйте, Shmj, Вы писали:

S>Кратко так:


Кратко не так, а вот так: кто угадает на какие именно грабли я наступил?
Re[26]: Ошибка, если конструктор определен в h-файле (этюд?)
От: rg45 СССР  
Дата: 06.07.23 07:57
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Умный всегда сомневается ,а дурак всегда уверен.

S>Я сомневаюсь что у тебя есть рабочее решение.

Так а хрен ли ты тогда выдрючиваешься, если сомневаешься?

Попробуйте сделать и обломитесь.


Вот это слишком борзый выпад для сомневающегося человека, тебе не кажется?
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[16]: Ошибка, если конструктор определен в h-файле (этюд?)
От: B0FEE664  
Дата: 06.07.23 08:00
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Однако же в таком случае — вопрос бы получил ответ. Пока ответа полноценного нет.

Условие для полноценного ответа все еще в силе здесь
Автор: B0FEE664
Дата: 05.07.23
И каждый день — без права на ошибку...
Re[19]: Ошибка, если конструктор определен в h-файле (этюд?)
От: so5team https://stiffstream.com
Дата: 06.07.23 08:04
Оценка:
Здравствуйте, rg45, Вы писали:

R>Придурок, это классическая проблема, с которой сталкивался каждый, кто использует идиoму скрытой реализации (PImpl). Это только для тебя это является открытием.


Я все же думаю, что здесь ситуация несколько хитрее.

Вот что придумалось:

Файл demo.hpp
// demo.hpp
#pragma once

#include <memory>

class Class2;

class Class1 {
    template<typename C>
    static int get_v() {
        C v;
        return v.value();
    }

    int v_{ get_v<Class2>() };

public:
    Class1();
    ~Class1();

    static std::unique_ptr<Class1> make();
};


Файл demo.cpp
// demo.cpp
#include "demo.hpp"

class Class2 {
public:
    int value() const { return 0; }
};

Class1::Class1() {}
Class1::~Class1() {}

std::unique_ptr<Class1> Class1::make() { return std::make_unique<Class1>(); }


Файл main.cpp
#include "demo.hpp"

int main() {
    auto c = Class1::make();
}


Компилировал под Ubuntu 22.04 так: clang++-16 -o demo -std=c++17 main.cpp demo.cpp
Поскольку clang работает поверх стандартной библиотеки от GCC, то диагностика при переносе конструктора в .hpp-файл такая:
In file included from main.cpp:1:
./demo.hpp:10:5: error: variable has incomplete type 'Class2'
                C v;
                  ^
./demo.hpp:14:10: note: in instantiation of function template specialization 'Class1::get_v<Class2>' requested here
        int v_{ get_v<Class2>() };
                ^
./demo.hpp:5:7: note: forward declaration of 'Class2'
class Class2;
      ^
1 error generated.

Возможно, если будет родная stdlib от clang-а (как на MacOS), то и диагностика будет другой. Но я сильно сомневаюсь. Так что, предположу, грабли у ТС-а все-таки другие.
Re[17]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 06.07.23 08:18
Оценка: :)))
Здравствуйте, B0FEE664, Вы писали:

S>>Однако же в таком случае — вопрос бы получил ответ. Пока ответа полноценного нет.

BFE>Условие для полноценного ответа все еще в силе здесь
Автор: B0FEE664
Дата: 05.07.23


Вы сейчас позорите честь форума и подтверждаете анекдот:

Американский форум- задал вопрос, тебе на него обстоятельно и вежливо ответят.
Еврейский форум- задал вопрос, тебе зададут встречный вопрос.
Русский форум-задал вопрос, тебе ещё 2 часа будут объяснять какой ты мудак!

Re[18]: Ошибка, если конструктор определен в h-файле (этюд?)
От: so5team https://stiffstream.com
Дата: 06.07.23 08:20
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Вы сейчас позорите честь форума и подтверждаете анекдот:


S>

S>Американский форум- задал вопрос, тебе на него обстоятельно и вежливо ответят.
S>Еврейский форум- задал вопрос, тебе зададут встречный вопрос.
S>Русский форум-задал вопрос, тебе ещё 2 часа будут объяснять какой ты мудак!


Ну попробуйте задать свой вопрос на американском форуме. Делов-то.
Re[3]: Ошибка, если конструктор определен в h-файле (этюд?)
От: ArtDenis Россия  
Дата: 06.07.23 08:23
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Текст ошибки: invalid application of 'sizeof' to an incomplete type 'namespace1::Class2'


Я имел ввиду полный вывод компилятора об этой ошибке
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re[18]: Ошибка, если конструктор определен в h-файле (этюд?)
От: B0FEE664  
Дата: 06.07.23 08:25
Оценка: +3
Здравствуйте, Shmj, Вы писали:

S>Вы сейчас позорите честь форума и подтверждаете анекдот:


Shmj, это не справедливо. Я вас нигде не оскорблял и не обижал.
Кстати, на американском форуме вопросы подобного рода (без всякого обсуждения) быстро закрывают с формулировкой вида "нет примера для воспроизведения проблемы".
И каждый день — без права на ошибку...
Re[8]: Ошибка, если конструктор определен в h-файле (этюд?)
От: serg_joker Украина  
Дата: 06.07.23 08:51
Оценка: +4
Здравствуйте, Videoman, Вы писали:

V>Потому что дело не только в конструкторе, но и в деструкторе. std::unique_ptr<Class2> деструктор для неполного объекта также не может создать. С деструктором Class1 проделай тоже самое:


Вот зачем ты помогаешь этому персонажу?
Это как на дороге: длинная тянучка, и все дисциплинировано едут.
И тут кто-то "самый умный" обгоняет всех через сплошную (или по обочине, по вкусу) и пытается вклиниться в поток. И его обязательно кто-то впустит. И в следующий раз он сделает ровно так же.
И в понимании этого шумахера будет "все лохи и ездить не умеют, а я красавчик, сломал систему".
Вот так и этот придурок.
Не нужно таким помогать, они, в итоге, делают всем хуже (ну кроме себя, конечно).
Отредактировано 06.07.2023 8:58 serg_joker . Предыдущая версия .
Re[20]: Ошибка, если конструктор определен в h-файле (этюд?)
От: rg45 СССР  
Дата: 06.07.23 09:07
Оценка:
Здравствуйте, so5team, Вы писали:


S>Я все же думаю, что здесь ситуация несколько хитрее.

S>Возможно, если будет родная stdlib от clang-а (как на MacOS), то и диагностика будет другой. Но я сильно сомневаюсь. Так что, предположу, грабли у ТС-а все-таки другие.

У меня описанные симптомы воспроизводятся в самом классическом варианте:

class Class1
{
public:

   Class1();
   ~Class1();

private:

   class Impl;

   std::unique_ptr<Impl> m;
};


При переносе определения конструктора из cpp в тело класса получаю ошибку:

C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.34.31933\include\memory(3105,1): error C2027: use of undefined type 'Class1::Impl'


Visual Studio 2022 v17.6.4, toolset v143, /std:c++20

Вероятно, воспроизводимость чувствительна к компилятору и реализации STL.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[21]: Ошибка, если конструктор определен в h-файле (этюд?)
От: so5team https://stiffstream.com
Дата: 06.07.23 09:20
Оценка:
Здравствуйте, rg45, Вы писали:

R>У меня описанные симптомы воспроизводятся в самом классическом варианте:


Да, вы правы, на классическом PImpl получается ошибка, как раз с нужной диагностикой:
$ clang++-16 -o demo -std=c++17 main.cpp demo.cpp
In file included from main.cpp:1:
In file included from ./demo.hpp:3:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/memory:76:
/usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/unique_ptr.h:83:16: error: invalid application of 'sizeof' to an incomplete type 'Class1::Impl'


Вероятно, это я перемудрил

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

S>Но мне кажется, что Class1 по любому должен создаваться через какую-то фабрику, а не просто как значение на стеке (или в агрегате).


Да и на стеке тоже должно воспроиводиться, почему нет. привожу ниже полный листинг моего варианта:

  Class1.h
#pragma once

#include <memory>

class Class1
{
public:

   Class1();
   ~Class1();

private:

   class Impl;

   std::unique_ptr<Impl> m;
};

  Class1.cpp
#include "Class1.h"

class Class1::Impl { };
Class1::Class1() { }
Class1::~Class1() { }

  main.cpp
#include "Class1.h"

int main()
{
   Class1 c;
}


Это успешная версия. После переноса конструктора, появляется ошибка.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 06.07.2023 9:26 rg45 . Предыдущая версия .
Re[23]: Ошибка, если конструктор определен в h-файле (этюд?)
От: so5team https://stiffstream.com
Дата: 06.07.23 09:34
Оценка: +1
Здравствуйте, rg45, Вы писали:

S>>Но мне кажется, что Class1 по любому должен создаваться через какую-то фабрику, а не просто как значение на стеке (или в агрегате).


R>Да и на стеке тоже должно воспроиводиться, почему нет.

R>Это успешная версия. После переноса конструктора, появляется ошибка.

Потому что Shmj говорил, что изначально у Class1 вообще явно определенного конструктора не было, был только дефолтный, сгенерированный самим компилятором. Если я правильно понимаю, то вот в таком случае:
class Class2;

class Class1 {
  std::unique_ptr<Class2> ptr_member_;
public:
  // Нет ни конструктора, ни деструктора.
};

int main() {
  Class1 c;
}

компиляция должна завершиться с ошибкой, т.к. здесь нет определения Class2.

Но вот в таком случае все OK:
class Class2;

class Class1 {
  std::unique_ptr<Class2> ptr_member_;
public:
  // Нет ни конструктора, ни деструктора.

  static std::unique_ptr<Class1> make();
};

int main() {
  auto c = Class1::make();
}


Да и вообще класс с PImpl, у которого конструктор генерируется самим компилятором... Ну звучит как такое себе.
Re[19]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 06.07.23 09:38
Оценка: :))) :)))
Здравствуйте, so5team, Вы писали:

S>Ну попробуйте задать свой вопрос на американском форуме. Делов-то.


Пока даю шанс России.
Re[24]: Ошибка, если конструктор определен в h-файле (этюд?)
От: rg45 СССР  
Дата: 06.07.23 09:41
Оценка: +1
Здравствуйте, so5team, Вы писали:

S>Потому что Shmj говорил, что изначально у Class1 вообще явно определенного конструктора не было, был только дефолтный, сгенерированный самим компилятором.


Для рассматриваемого случая принципиальной разницы нет — что дефолтный конструктор, определенный компилятором, что дефолтный конструктор, определенный пользователем в теле класса, — оба варианта приводят к одной и той же ошибке.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[20]: Ошибка, если конструктор определен в h-файле (этюд?)
От: rg45 СССР  
Дата: 06.07.23 09:44
Оценка: :))
Здравствуйте, Shmj, Вы писали:

S>Пока даю шанс России.


Цирк уехал, а Shmj остался.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[25]: Ошибка, если конструктор определен в h-файле (этюд?)
От: so5team https://stiffstream.com
Дата: 06.07.23 09:47
Оценка: +1
Здравствуйте, rg45, Вы писали:

S>>Потому что Shmj говорил, что изначально у Class1 вообще явно определенного конструктора не было, был только дефолтный, сгенерированный самим компилятором.


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


Это да. Просто хотелось понять, как Shmj умудрялся работать с экземплярами Class1, если в Class1 не было явно описанного пользователем конструктора.
Re[21]: Ошибка, если конструктор определен в h-файле (этюд?)
От: so5team https://stiffstream.com
Дата: 06.07.23 09:47
Оценка:
Здравствуйте, rg45, Вы писали:

R>Цирк уехал, а Shmj остался.


А он разве остался?
Re[26]: Ошибка, если конструктор определен в h-файле (этюд?)
От: rg45 СССР  
Дата: 06.07.23 09:49
Оценка:
Здравствуйте, so5team, Вы писали:

S>Это да. Просто хотелось понять, как Shmj умудрялся работать с экземплярами Class1, если в Class1 не было явно описанного пользователем конструктора.


Ну так, возможно, до него все работало и с автоматически сгенерированным конструктором. Не зря же он подключился к проекту
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[27]: Ошибка, если конструктор определен в h-файле (этюд?)
От: so5team https://stiffstream.com
Дата: 06.07.23 09:54
Оценка: +1
Здравствуйте, rg45, Вы писали:

S>>Это да. Просто хотелось понять, как Shmj умудрялся работать с экземплярами Class1, если в Class1 не было явно описанного пользователем конструктора.


R>Ну так, возможно, до него все работало и с автоматически сгенерированным конструктором.


"Но черт возьми, Холмс, как?"

Мне вот было любопытно, как в Class1 создается и инициализируется что-то связанное с Class2, при этом не имея определения Class2.
Но, похоже, там просто unique_ptr, который изначально пустой, а значение ему назначается позже. Что-то вроде:
class Class1 {
  std::unique_ptr<Class2> ptr_member_;

  void do_something(); // Реализовано в .cpp-файле.
  ...
};

void Class1::do_something() {
  if(!ptr_member_) ptr_member_ = std::make_unique<Class2>(...);
  ...
}

Тогда работа дефолтного, сгенерированного компилятором конструктора становится понятной.
Re[25]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 06.07.23 12:25
Оценка: :)
Здравствуйте, rg45, Вы писали:

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


Этот вариант уже предлагали и вот мой ответ на него: https://rsdn.org/forum/cpp/8557491.1
Автор: Shmj
Дата: 06.07.23


В общем, чует моя душа — придется таки выцеживать из проекта мин. код.
Re[26]: Ошибка, если конструктор определен в h-файле (этюд?)
От: rg45 СССР  
Дата: 06.07.23 12:29
Оценка: +4
Здравствуйте, Shmj, Вы писали:

S>Этот вариант уже предлагали и вот мой ответ на него: https://rsdn.org/forum/cpp/8557491.1
Автор: Shmj
Дата: 06.07.23


S>В общем, чует моя душа — придется таки выцеживать из проекта мин. код.


А моя душа чует, что ты немножко гонишь.

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

http://rsdn.org/forum/cpp/8557130.1
Автор: Shmj
Дата: 05.07.23


Мне не нужно знать в чем проблема была именно в том частном случае.
Мне нужно понимание почему вообще перенос пустого конструктора в H-файл может приводить к ошибке компиляции — какая разница компилятору?


Когда тебе ответили на поставленный вопрос: "почему вообще так может быть?", оказалось, что "у тебя был другой кейс". Так ты сам определись сначала, что ты хочешь — чтоб твои "этюды" решали, или чтоб тебе разрулили то, что ты там наговнокодил за кулисами, и не морочь людям головы.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 06.07.2023 12:49 rg45 . Предыдущая версия . Еще …
Отредактировано 06.07.2023 12:36 rg45 . Предыдущая версия .
Отредактировано 06.07.2023 12:35 rg45 . Предыдущая версия .
Отредактировано 06.07.2023 12:34 rg45 . Предыдущая версия .
Re[27]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 06.07.23 12:52
Оценка: :))) :))
Здравствуйте, rg45, Вы писали:

R>Когда тебе ответили на поставленный вопрос: "почему вообще так может быть?", оказалось, что "у тебя был другой кейс". Так ты сам определись сначала, что ты хочешь — чтоб твои "этюды" решали, или чтоб тебе разрулили то, что ты там наговнокодил за кулисами, и не морочь людям головы.


В принципе да, на первоначальный вопрос ответили. Но тут же начало распирать любопытство — а как же у меня могло работать с конструктором по умолчанию? Ну не создавать же новую тему?
Re[28]: Ошибка, если конструктор определен в h-файле (этюд?)
От: rg45 СССР  
Дата: 06.07.23 13:02
Оценка:
Здравствуйте, Shmj, Вы писали:

S>В принципе да, на первоначальный вопрос ответили. Но тут же начало распирать любопытство — а как же у меня могло работать с конструктором по умолчанию? Ну не создавать же новую тему?


На колу мочало, начинай сначала: http://rsdn.org/forum/cpp/8556819.1
Автор: so5team
Дата: 05.07.23
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[28]: Ошибка, если конструктор определен в h-файле (этюд?)
От: rg45 СССР  
Дата: 06.07.23 13:10
Оценка:
Здравствуйте, Shmj, Вы писали:


S>Но тут же начало распирать любопытство — а как же у меня могло работать с конструктором по умолчанию?


Вообще, странный вопрос — в каком смысле "могло"? Сейчас у же перестало, что ли? Так может помимо этого были сделаны еще какие-то изменения, не рассматривал такой вариант?
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[29]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 06.07.23 14:29
Оценка: :)
Здравствуйте, rg45, Вы писали:

S>>Но тут же начало распирать любопытство — а как же у меня могло работать с конструктором по умолчанию?


R>Вообще, странный вопрос — в каком смысле "могло"? Сейчас у же перестало, что ли? Так может помимо этого были сделаны еще какие-то изменения, не рассматривал такой вариант?


Можно и сейчас сделать. Может потом займусь, если никто не догадается как такое можно сделать.
Re[28]: Ошибка, если конструктор определен в h-файле (этюд?)
От: rg45 СССР  
Дата: 06.07.23 14:34
Оценка:
Здравствуйте, Shmj, Вы писали:


S>Но тут же начало распирать любопытство — а как же у меня могло работать с конструктором по умолчанию?


И научись уже использовать правильную терминологию, чтоб не приходилось тебя разгадывать как ребус. Конструкторы по умолчанию бывают определенные пользователем и могут быть определены неявно компилятором. Так какой из них ты имел в виду? (Можешь не отвечать, вопрос риторический).
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[30]: Ошибка, если конструктор определен в h-файле (этюд?)
От: so5team https://stiffstream.com
Дата: 06.07.23 14:43
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Может потом займусь, если никто не догадается как такое можно сделать.


Да давно уже догадались
Автор: so5team
Дата: 06.07.23
. Можете закоментировать конструктор/деструктор в demo.hpp/cpp и все будет компилироваться. А если определите конструктор по умолчанию прямо в demo.hpp, то перестанет.

Так что решение вашему условию
Автор: Shmj
Дата: 06.07.23
удовлетворяет. Но есть подозрение, что это не то, что вам было нужно.
Re[30]: Ошибка, если конструктор определен в h-файле (этюд?)
От: rg45 СССР  
Дата: 06.07.23 14:57
Оценка: 4 (1) +1
Здравствуйте, Shmj, Вы писали:

S>Можно и сейчас сделать. Может потом займусь, если никто не догадается как такое можно сделать.


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

http://coliru.stacked-crooked.com/a/3ff6997251bdabcc

#include <memory>

class Class1
{
public:

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

private:

   class Impl;

   std::unique_ptr<Impl> m;
};

int main()
{
}


Раскомментируешь дефолтный конструктор, определенный инлайном в классе, и — получите, распишитесь:

http://coliru.stacked-crooked.com/a/1840c0de42ea99a3

g++ -std=c++11 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
/usr/local/include/c++/12.1.0/bits/unique_ptr.h:93:23: error: invalid application of 'sizeof' to incomplete type 'Class1::Impl'
   93 |         static_assert(sizeof(_Tp)>0,
      |                       ^~~~~~~~~~~


Выносим определение дефолтного конструктора в cpp, и снова все чики-пуки:

http://coliru.stacked-crooked.com/a/a866ea1051987c33
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 06.07.2023 15:13 rg45 . Предыдущая версия . Еще …
Отредактировано 06.07.2023 15:04 rg45 . Предыдущая версия .
Re[31]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 06.07.23 15:00
Оценка:
Здравствуйте, so5team, Вы писали:

S>Да давно уже догадались
Автор: so5team
Дата: 06.07.23
. Можете закоментировать конструктор/деструктор в demo.hpp/cpp и все будет компилироваться. А если определите конструктор по умолчанию прямо в demo.hpp, то перестанет.


In file included from /Users/test/Desktop/cmake_test/main.cpp:1:
/Users/test/Desktop/cmake_test/Class1.h:11:11: error: variable has incomplete type 'Class2'
C v;
^
/Users/test/Desktop/cmake_test/Class1.h:15:13: note: in instantiation of function template specialization 'Class1::get_v<Class2>' requested here
int v_{ get_v<Class2>() };
^
/Users/test/Desktop/cmake_test/Class1.h:6:7: note: forward declaration of 'Class2'
class Class2;
^
1 error generated.


Вот странно, у меня такая ошибка с вашим оригинальным кодом, ничего не переносил в H-файл.
Re[32]: Ошибка, если конструктор определен в h-файле (этюд?)
От: so5team https://stiffstream.com
Дата: 06.07.23 15:06
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Вот странно, у меня такая ошибка с вашим оригинальным кодом, ничего не переносил в H-файл.


У меня с clang-16 OK, с clang-14 ошибка.
Re[31]: Ошибка, если конструктор определен в h-файле (этюд?)
От: serg_joker Украина  
Дата: 06.07.23 15:17
Оценка: +1 :))) :)))
Здравствуйте, rg45, Вы писали:

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

Слабак!
Re[32]: Ошибка, если конструктор определен в h-файле (этюд?)
От: rg45 СССР  
Дата: 06.07.23 15:21
Оценка:
Здравствуйте, serg_joker, Вы писали:

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

_>Слабак!

И это не первая победа упрямства над разумом.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 06.07.2023 15:22 rg45 . Предыдущая версия .
Re[32]: Ошибка, если конструктор определен в h-файле (этюд?)
От: so5team https://stiffstream.com
Дата: 06.07.23 15:34
Оценка: 9 (1)
Здравствуйте, Shmj, Вы писали:

S>Вот странно, у меня такая ошибка с вашим оригинальным кодом, ничего не переносил в H-файл.


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

demo.hpp
#pragma once

#include <memory>

class Class1
{
public:

   Class1();
   ~Class1();

   static std::unique_ptr<Class1> make();

private:

   class Impl;

   std::unique_ptr<Impl> m;
};


demo.cpp
#include "demo.hpp"

class Class1::Impl {
};

Class1::Class1() {}
Class1::~Class1() {}

std::unique_ptr<Class1> Class1::make() { return std::make_unique<Class1>(); }


main.cpp
#include "demo.hpp"

int main() {
    auto c = Class1::make();
}
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...
Пока на собственное сообщение не было ответов, его можно удалить.