Здравствуйте, velkin, Вы писали:
V>У меня по Страуструпу есть даже печатная книга "Язык программирования C++. 3-е издание. 1999 год", как раз купленная где-то тогда мною лично для себя.
Купи новую версию. Как минимум, было ещё Special Edition, в которое долили воды, и ещё почти современное переиздание, 4ое. Но это толстая книга. Прочти сначала тонкие, потом толстую, а потом Майрсов с Александресками дозированно читай, только дозированно, а то будет перетоксикоз шаблонами. Но лучше это на потом, а пока почитай книжки с участием Джосаттиса, толстячки, но читаются легко, у меня две, одна целиком его, другая в соавторстве, может ещё какие-то есть.
Это уже всё довольно старое по нонешним меркам, но подтянутся поможет
Здравствуйте, Великий Реверс, Вы писали:
ВР>ну и зачем все эти сборки макулатуры, вы под деда лаптеева косите что ли?
ВР>курса Констатина Владимирова про андвенсед С++ на ютубе ВР>абсолютно достаточно что бы подтянуть основные часто используемые знания по С++20 включительно
Здравствуйте, Marty, Вы писали:
M>>>Два или больше раз включать одно и тоже можно замечательно, и это не вызовет ошибку компиляции, если ты понимаешь, что делаешь
V>>Может и не вызвать ошибки компиляции, но зачем? Вот напишешь несколько раз объявления без определений и оно прокатит. Но практического смысла я не вижу. Напиши код который имеет смысл, я хоть посмотрю зачем это кому-то надо было.
M>Например, у меня была ситуация, когда шаблонный using не работал как надо (да, не самый новый компилятор), и втащить корректно сущность в другой namespace не получалось. Но каждый раз использовать сущность с указанием её namespace не хотелось. Тогда я поместил эту сущность в файл без namespace, и стал инклюдить куда надо. Да, костыль, да, дублирование кода, да и пофик, зато делает что мне нужно.
Тут можно продолжить в строну namespace: включаемый код может содержать макросы (такие как BEGIN/END/ASSERT),
которыми можно менять поведение включаемого кода в зависимости от сборки или/и внешнего заголовка,
и получить пространства имён типа debugCall/safeCall/fastCall, которыми можно уже пользоваться осмысленно.
Тут и стражи, и повторное использование, и циклические включения, чего с pragma once не получится добиться.
Здравствуйте, velkin, Вы писали:
V>Читал я тут очередную книгу по C++ и мне внезапно подумалось, а нужны ли стражи включения.
Допустим, у тебя есть заголовочник A, который определяет какие-то базовые понятия, и заголовочники B и C, которые этими понятиями пользуются.
Как их использовать? Каждый раз требовать, чтобы программист включал их все, да еще и в правильном порядке?
При наличии механизма, который делает безопасным повторное включение одного и того же заголовочника, зависимые заголовочники B и C могут сами навключать себе то, чти и нужно, не вызывая хаоса в программе.
Проблема ненужных #include понятна. По-хорошему, компилятор мог бы анализировать код и выдавать предупреждения по поводу лишних #include. Но к сожалению, он этого не делает.
Есть и еще одна проблема. Явно включенные заголовочники могут притащить по своим зависимостям какие-то другие, и программа может пользоваться символами из этих неявных включений, сама явно их не включая. Такая конструкция имеет тенденцию иногда ломаться. Тут тоже мог бы помочь компилятор, но увы, он этого не делает.
Здравствуйте, velkin, Вы писали:
V>А я подумал о том, что зачем это не сделали по умолчанию опцией компилятора, то есть автоматическим стражем включения для каждого файла.
Ты не видел, как делается метапрограммирование на С? Не видел, как один хедер два раза инклюдят, но с разными дефайнами, чтоб одни и те же алгоритмы для разных типов получить?
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, Pzz, Вы писали:
Pzz>Проблема ненужных #include понятна. По-хорошему, компилятор мог бы анализировать код и выдавать предупреждения по поводу лишних #include. Но к сожалению, он этого не делает. Clangd делает.
Pzz>Есть и еще одна проблема. Явно включенные заголовочники могут притащить по своим зависимостям какие-то другие, и программа может пользоваться символами из этих неявных включений, сама явно их не включая. Такая конструкция имеет тенденцию иногда ломаться. Тут тоже мог бы помочь компилятор, но увы, он этого не делает.
Пример?
Здравствуйте, Skorodum, Вы писали:
Pzz>>Есть и еще одна проблема. Явно включенные заголовочники могут притащить по своим зависимостям какие-то другие, и программа может пользоваться символами из этих неявных включений, сама явно их не включая. Такая конструкция имеет тенденцию иногда ломаться. Тут тоже мог бы помочь компилятор, но увы, он этого не делает. S>Пример?
#include <string.h> приносит size_t (из stddef.h). Потом мы string.h> убираем, а stddef.h забываем явно включить, и получаем ататашечку.
Это в libc. В ней все еще более-менее аккуратно сделано. В сторонних библиотеках возможны и более заковыристые варианты, но пример навскидку не приведу.
Здравствуйте, Pzz, Вы писали:
Pzz>#include <string.h> приносит size_t (из stddef.h). Потом мы string.h> убираем, а stddef.h забываем явно включить, и получаем ататашечку.
1. Clangd умеет предупреждать когда необходимые объявления не включены явно.
2. Clangd умеет предупреждать когда необходимые объявления не включены.
2. Ошибка во время компиляции это не проблема ни разу.
Здравствуйте, Skorodum, Вы писали:
S>Здравствуйте, Pzz, Вы писали:
Pzz>>#include <string.h> приносит size_t (из stddef.h). Потом мы string.h> убираем, а stddef.h забываем явно включить, и получаем ататашечку. S>1. Clangd умеет предупреждать когда необходимые объявления не включены явно. S>2. Clangd умеет предупреждать когда необходимые объявления не включены.
Я не знал. Я как-то больше привык к gcc
S>2. Ошибка во время компиляции это не проблема ни разу.
Она становится проблемой, когда у тебя несколько разных дистрибутивов линуха под присмотром, и ошибка вылезнает не на том/тех, на которых ты обычно работаешь. К сожалению, разные опции сборки библиотек и компиляторов иногда "радуют" такими сюрпризами.
Здравствуйте, Pzz, Вы писали:
Pzz>Я не знал. Я как-то больше привык к gcc
Так я тоже в основном gcc использую, но Clangd это не компилятор, а "языковой сервер" (построенный на базе компилятора Clang). Его редакторы и среды разработки используют.
Pzz>Она становится проблемой, когда у тебя несколько разных дистрибутивов линуха под присмотром, и ошибка вылезнает не на том/тех, на которых ты обычно работаешь. К сожалению, разные опции сборки библиотек и компиляторов иногда "радуют" такими сюрпризами.
Я с этим не спорю, я больше про то, что такие ошибки это не большая проблема в принципе, да надо исправить и пересобрать, но это не UB или SEGFAULT во время выполнения.
Здравствуйте, velkin, Вы писали:
V>Но вот вопрос в каких случаях нужно вставить один файл в другой несколько раз? Я ни разу не встречался с таким явлением. Может кто опытней знает зачем?
Препроцессорная магия. На голом Си такое делают. На плюсах она нужна в гораздо меньшей степени, но если общая для си и плюсов кодовая база, или если надо чего-то особенного...
V> И возник вопрос, что имели в виду создатели языка, то есть Страуструп и прочий комитет? Что они подразумевали проектируя препроцессор?
Препроцессор проектировал не Страуструп, а Керниган и Ричи.
А С++ его унаследовал. В том числе, для частичной совместимости с Си.
V>Тот же Страуструп любит рассуждать про логическую и физическую структуру программы. А в итоге получается, что страж включения это костыль, который избавляет нас от ручного управления физической структурой программы и позволяет прописывать сколько угодно включений.
К инклудам уже так все привыкли, что нормальные модули сделать не могут.
Как и нормальные экспорты шаблонов.