Здравствуйте, FrozenHeart, Вы писали:
FH>Выглядит это всё примерно следующим образом:
Пример уж слишком минимизированный.
FH> Добавление необходимых в "exception.h" функций из заголовочного файла "filesystem.h" лишь успокоит компилятор, однако добавит дублирование кода.
Скорее всего нет необходимости в зависимости базового класса исключений от filesystem.h. Не могу представить себе в каких случаях это действительно необходимо.
Re: Разрешение зависимостей при включении заголовочных файлов в C++
FH>Как бы Вы исправили подобную ситуацию? Добавление необходимых в "exception.h" функций из заголовочного файла "filesystem.h" лишь успокоит компилятор, однако добавит дублирование кода.
Я бы имел оба раза по файлу с декларациями и с реализациями. И Декларации fs зависели бы от деклараций исключений, а реализация обоих, зависелы от деклараций обоих...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Разрешение зависимостей при включении заголовочных файлов в C++
Здравствуйте, FrozenHeart, Вы писали:
FH>Есть два заголовочных файла -- "exception.h" и "filesystem.h". Первый содержит определение базового класса исключений, используемых в проекте, а второй -- функции для различного взаимодействия с FS, а также определение класса исключений, наследуемого от того самого базового класса из "exception.h".
FH> "exception.h" же, в свою очередь, для реализации базового класса исключений нужно несколько функций из "filesystem.h".
Либо здесь какая-то ошибка проектирования (зачем в exception.h файловая система?),
либо можно ограничиться forward declaration, как, например, <iostream> предобъявляет std::string, но не #include <string>
либо надо разнести объявления и определения — exception.h и exception-impl.h например, или filesystem.h и filesystem.cpp
Перекуём баги на фичи!
Re[3]: Разрешение зависимостей при включении заголовочных файлов в C++
Здравствуйте, FrozenHeart, Вы писали:
FH>Например, для конструирования объекта класса debug::location, конструктор которого принимает в качестве аргумента строку, получаемую в результате "отделения" имени файла от полного пути до него (именно такая функция, помимо всего прочего, и есть в "filesystem.h").
Конкретно здесь это плохая затея.
Во-первых, расщепление строки на подстроки не должно кидать пользовательские исключения, особенно в тех случаях, когда происхождение строки (__FILE__) очевидно. Если компилятор сглючил и подсунул мусор, то кидать исключения поздно.
Так что можно было бы написать очень простую nothrow-версию, или версию, кидающую только std::bad_alloc из недр std::string.
Во-вторых, в солюшене запросто могут быть одноимённые файлы (в разных проектах), и даже в одном проекте (хедеры в разных каталогах).
Затирать пути — это лишать себя ценной информации.
Если структура каталогов компьютера, на котором собирается программа в продакшен, не должна быть засвечена, — то выход очень простой.
или аналогично с симлинками — хоть в виндах, хоть в никсах.
К>> либо можно ограничиться forward declaration, как, например, <iostream> предобъявляет std::string, но не #include <string> К>> либо надо разнести объявления и определения — exception.h и exception-impl.h например, или filesystem.h и filesystem.cpp
FH>Если вдаваться в конкретику, то в моём случае это код header-only библиотеки.
<iostream> и <string> — тоже header-only, тоже содержат перекрёстные ссылки, — и там это разруливается предобъявлениями и шаблонами.
А разбиение хедера на файл с объявлениями и файл с инлайн-определениями позволит сделать потом мета-хедер, включающий все четыре части (объявления exception, объявления filesystem, определения того и другого) в нужном порядке.
Перекуём баги на фичи!
Разрешение зависимостей при включении заголовочных файлов в C++
Имеется следующая ситуация (точнее, её упрощённый вариант, чтобы проблему можно было увидеть на минимальном примере):
Есть два заголовочных файла -- "exception.h" и "filesystem.h". Первый содержит определение базового класса исключений, используемых в проекте, а второй -- функции для различного взаимодействия с FS, а также определение класса исключений, наследуемого от того самого базового класса из "exception.h". "exception.h" же, в свою очередь, для реализации базового класса исключений нужно несколько функций из "filesystem.h".
Собственно, несложно заметить, что в таком случае мы имеем дело с рекурсией, в результате чего получаем вполне резонную ошибку компиляции:
error C2504: 'exception' : base class undefined
Как бы Вы исправили подобную ситуацию? Добавление необходимых в "exception.h" функций из заголовочного файла "filesystem.h" лишь успокоит компилятор, однако добавит дублирование кода.
Здравствуйте, FrozenHeart, Вы писали: FH>
[ccode]
// exception.h
#ifndef EXCEPTION_H
#define EXCEPTION_H
#include "filesystem.h"
class exception {};
#endif // !EXCEPTION_H
[ccode] FH>// exception.h
это зачем еще исключению знать детали реализации filesystem? не, ну может быть оно ей и правда нужно, но уж точно в реализации, а не в обьявлении. да и даже если в обьявлении вдруг приспичит, например, передавать исключению указатель на файл, то это решается так:
[ccode]
#ifndef EXCEPTION_H
#define EXCEPTION_H
//#include "filesystem.h" — нафиг
class File;
class exception {};
[ccode]
Re[2]: Разрешение зависимостей при включении заголовочных файлов в C++
К> Либо здесь какая-то ошибка проектирования (зачем в exception.h файловая система?),
Например, для конструирования объекта класса debug::location, конструктор которого принимает в качестве аргумента строку, получаемую в результате "отделения" имени файла от полного пути до него (именно такая функция, помимо всего прочего, и есть в "filesystem.h").
К> либо можно ограничиться forward declaration, как, например, <iostream> предобъявляет std::string, но не #include <string> К> либо надо разнести объявления и определения — exception.h и exception-impl.h например, или filesystem.h и filesystem.cpp
Если вдаваться в конкретику, то в моём случае это код header-only библиотеки.
Здравствуйте, FrozenHeart, Вы писали: К>> Либо здесь какая-то ошибка проектирования (зачем в exception.h файловая система?), FH>Например, для конструирования объекта класса debug::location, конструктор которого принимает в качестве аргумента строку, получаемую в результате "отделения" имени файла от полного пути до него (именно такая функция, помимо всего прочего, и есть в "filesystem.h").
вообще, все уши торчат из кривой библиотеки.
кстати, если библиотека задизайнена криво, то обычно там и багов полно. поэтому стоит ее проверить хорошенько, а лучше отказаться
если же говорить конструктивно — как все исправить, то можно облявление debug::location вынести в отдельный файл.
в любом случае обьявление exception не должно включать filesystem
Re: Разрешение зависимостей при включении заголовочных файлов в C++
Здравствуйте, FrozenHeart, Вы писали:
FH>Как бы Вы исправили подобную ситуацию? Добавление необходимых в "exception.h" функций из заголовочного файла "filesystem.h" лишь успокоит компилятор, однако добавит дублирование кода.
Здравствуйте, Erop, Вы писали:
E>Я бы имел оба раза по файлу с декларациями и с реализациями. И Декларации fs зависели бы от деклараций исключений, а реализация обоих, зависелы от деклараций обоих...
А вообще такой спор был 2-3 года назад. Логика понятна, а проблемы решаются дефайнами или once
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.