Здравствуйте, Muxa, Вы писали:
M>А в чем была проблема с включением файла по симлинку/хардлинку в gcc?
Если к одному файлу можно добраться двумя разными путями. Например,
/some/MyCoolLib/include/mycool/foo.h
/some/MyCoolLib-1.2.3/include/mycool/foo.h
где версия 1.2.3 является актуальной.
То есть, хаотичное подключение в одном проекте (в разных единицах компиляции) одного и того же по содержанию foo.h из разных каталогов не является нарушением ODR.
Но может случиться так, что
/some/AnotherLib/include/another/bar.h
явно подключает хедер
#include"../MyCoolLib/include/mycool/foo.h"
тогда как в других местах все делают в расчёте на правильные конфиги
#include <mycool/foo.h>
// и тут внезапно встречается#include <another/bar.h>
Инклуд-гарды от такой проблемы спасают, но они должны быть уникальны во всём проекте.
Опять же, #pragma once компактнее, чем три строки с двумя одинаковыми идентификаторами (с риском опечататься и #ifndef ONE / #define ANOTHER)
Есть и ещё одна подводная грабля, а именно, препроцессорная магия. Причём, казалось бы, невинная (не тот ад и трэш, который делает бизон
)
Даже если хедеры бинарно совпадают, у них могут быть разные зависимости:
/site1/foo.h — #include "./bar.h"
/site1/bar.h — нечто специфичное для site1
/site2/foo.h — линк или копия /site1/foo.h
/site2/bar.h — совершенно другое содержимое, специфичное уже для site2
/altogether/all.h — #include <site1/foo.h> и <site2/foo.h>
Тут уже обычные гарды не прокатят, а прагма может коварно сломаться.
Здравствуйте, Кодт, Вы писали:
К>Но может случиться так, что К>/some/AnotherLib/include/another/bar.h К>явно подключает хедер К>
К>#include"../MyCoolLib/include/mycool/foo.h"
К>
К>тогда как в других местах все делают в расчёте на правильные конфиги К>
К>#include <mycool/foo.h>
К>// и тут внезапно встречается
К>#include <another/bar.h>
К>
Ну, тут ИМХО ничего не поможет, "когда в товарищах согласья нет". Я сам, конечно, не испытываю бешеного восторга от этой include-магии, но мы имеем то, что имеем, и если взялся за плюсы, то играй по их правилам.
Здравствуйте, Mr.Delphist, Вы писали:
MD>Ну, тут ИМХО ничего не поможет, "когда в товарищах согласья нет". Я сам, конечно, не испытываю бешеного восторга от этой include-магии, но мы имеем то, что имеем, и если взялся за плюсы, то играй по их правилам.
Как раз тут поможет старый добрый инклуд-гард.
Нельзя сказать, что это хорошо, потому что двойное включение — это гарантированный слом компиляции (и ибо вотще, надо наводить порядок в коде), а тихое включение потенциально не той версии — это нарушение ODR.
Здравствуйте, Кодт, Вы писали:
К>Если коротко: gcc для #pragma once использует не путь к файлу, а его атрибуты (размер и время) и содержимое.
классический #ifndef X/#define X
дает точно такой же эффект, за исключением того что не учитывает время файла.
— путь к файлу игнорируется, проверяется только содержимое
Здравствуйте, Кодт, Вы писали:
К>http://users.livejournal.com/_winnie/433617.html?view=5691601
К>Если коротко: gcc для #pragma once использует не путь к файлу
Это разумно если следовать правилу один
Хидер — один класс. Тогда внутрях они будут разделяться все равно по имени. Вопрос в том принтмаешь ли ты этот стиль кодирования или нет
Вот же козлы. Правда тот, кто не пишет комментариев и вообще шапки файлов -- ССЗБ
А #pragma once в стандарте есть?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Кодт, Вы писали:
К>Инклуд-гарды от такой проблемы спасают, но они должны быть уникальны во всём проекте.
Так же, как и имена классов, например.
К>Опять же, #pragma once компактнее, чем три строки с двумя одинаковыми идентификаторами (с риском опечататься и #ifndef ONE / #define ANOTHER)
А вообще-то автоматическое прописывание гардов при помощи макросни редактора или скриптов -- рулит
Ну и уникальность гардов в проекте тогда можно автоматически проверять...
К>Есть и ещё одна подводная грабля, а именно, препроцессорная магия. Причём, казалось бы, невинная (не тот ад и трэш, который делает бизон
) К>Даже если хедеры бинарно совпадают, у них могут быть разные зависимости: К>/site1/foo.h — #include "./bar.h" К>/site1/bar.h — нечто специфичное для site1
IMHO, это нарушение ODR...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Abyx, Вы писали:
A>дает точно такой же эффект, за исключением того что не учитывает время файла. A>- путь к файлу игнорируется, проверяется только содержимое
Обычно гарды если и не гарантированно уникальны на проект, то, как минимум, в них подмешивают имена файлов/классов...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
К>>Инклуд-гарды от такой проблемы спасают, но они должны быть уникальны во всём проекте. E>Так же, как и имена классов, например.
Не совсем. Есть несколько способов разрулить идентификаторы.
— static для переменных и функций, namespace{} для всех, включая классы, — чтобы не злить линкера
— формировать имя из макроса, данного извне
namespace MYLIB_AUX {
class PP_CAT(MYLIB,_Foo) { ..... };
}
— нахлобучивать namespace NS{} извне, — как это сделано, например, для <cstdio>
namespace mylib_aux {
#include <naked.h>
}
Это то, что сразу приходит в голову.
К>>Опять же, #pragma once компактнее, чем три строки с двумя одинаковыми идентификаторами (с риском опечататься и #ifndef ONE / #define ANOTHER)
E>А вообще-то автоматическое прописывание гардов при помощи макросни редактора или скриптов -- рулит E>Ну и уникальность гардов в проекте тогда можно автоматически проверять...
Определённая культура всё равно нужна.
Если у тебя куча библиотек с хедерами, и в каждой из них есть свой utils.h или config.h ...
Особенно, если библиотеки сторонние...
К>>Есть и ещё одна подводная грабля, а именно, препроцессорная магия. Причём, казалось бы, невинная (не тот ад и трэш, который делает бизон
) К>>Даже если хедеры бинарно совпадают, у них могут быть разные зависимости: К>>/site1/foo.h — #include "./bar.h" К>>/site1/bar.h — нечто специфичное для site1
E>IMHO, это нарушение ODR...
С чего бы это вдруг?
/* driver.h */#include"./driver_config.h"/* #define DRIVER_NAME your_driver_name_goes_here и т.п. полезняшки */void PP_CAT(init_,DRIVER_NAME) (void);
void PP_CAT(done_,DRIVER_NAME) (void);
int PP_CAT(call_,DRIVER_NAME) (char* cmd);
Конечно, эту магию можно и нужно переделывать, чтобы она была и красивее, и устойчивее к тонкостям препроцессора, — но, тем не менее...
Здравствуйте, Кодт, Вы писали:
К>Это то, что сразу приходит в голову.
Ну так гарды можно вообще скриптом проверять и генерить из GUIDов замену неуникальным, например...
Или какой-нибудь ID в файловой системе использовать, скажем. В целом есть много недорогих и практичых способов гарантировать уникальность отображения гардов на файл и обратно...
К>Определённая культура всё равно нужна.
Это таки да.
Но такие сложные замуты с хедерами, как ты показал, без "определённой культуры" вообще лучше бы не мутить, если честно К>Если у тебя куча библиотек с хедерами, и в каждой из них есть свой utils.h или config.h ... К>Особенно, если библиотеки сторонние...
Ну, заверни в изолирующий слой какой, например.
Но gcc со своим подходом всё равно козлы!
E>>IMHO, это нарушение ODR...
К>С чего бы это вдруг?
Ну смотри,
// a.hstruct params {
int DefaultId;
std::string Text;
};
// b.hstruct params {
std::string Text;
int DefaultId;
};
// foo.hinline int foo( const params& p )
{
const int realId = SomeStaticTable.FindId( p.Text );
return realId != NotFound ? realId : p.DefaultId;
}
ну и где-то в коде у нас
#include"a.h"
include "foo.h"
а где-то
#include"b.h"
include "foo.h"
Как думаешь, с ODR тут всё ok?..
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
К>>Если у тебя куча библиотек с хедерами, и в каждой из них есть свой utils.h или config.h ... К>>Особенно, если библиотеки сторонние...
E>Ну, заверни в изолирующий слой какой, например.
Для хедер-онли библиотек особо не позаворачиваешь. Придётся патчить.
Причём не факт, что где-нибудь не лежит закладка на конкретное имя гарда, — как это сделал бизон, и как тут уже коллега плакался (потому что у гуся и вижела гард для <stdlib.h> по-разному называется)
E>Но gcc со своим подходом всё равно козлы!
не козлы, а бараны.
E>>>IMHO, это нарушение ODR... К>>С чего бы это вдруг?
E>Ну смотри,
<...> E>Как думаешь, с ODR тут всё ok?..
Не. Как нарушать ODR — это я знаю и умею. И как не нарушать — тоже.
Я показал более-менее реалистичный пример, когда одинаковые файлы с разными зависимостями нужно загрузить вместе, но из-за ложного срабатывания прагмы это обломится.
Может быть, это даже не магия с именами, а скелет плагина
// plugin_all.h#pragma once
#include"./plugin_class.h"#include"./plugin_factory.h"#include"./plugin_tests.h"
где в зависимостях уже будут лежать class foo_plugin, class foo_factory и т.д.
Здравствуйте, Кодт, Вы писали:
К>Для хедер-онли библиотек особо не позаворачиваешь. Придётся патчить.
Во-первых, почему?
Во-вторых, ечли даже и патчить, но автоматом, то проблема невелика есть...
К>Причём не факт, что где-нибудь не лежит закладка на конкретное имя гарда, — как это сделал бизон, и как тут уже коллега плакался (потому что у гуся и вижела гард для <stdlib.h> по-разному называется)
Тоже автомат тут помогает, ну и потом мало ли какие говнобиблиотеки закладываются на неспециализированное или неопределённое поведение? Не надо использовать говно-код, особенно если ты не можешь его поправить
Да, это всё равно не отменяет моего мнения, что в этом вопросе гцц — козлы.
E>>Но gcc со своим подходом всё равно козлы! К>не козлы, а бараны.
Мне кажется, что в данном случае речь иджёт о ГМО, сочетающем свойства обеих видов
Я так думаю, что придумали они это сдуру, а внедрили и сохраняют потому, что нетривильный вендор-лок
К>Не. Как нарушать ODR — это я знаю и умею. И как не нарушать — тоже. К>Я показал более-менее реалистичный пример, когда одинаковые файлы с разными зависимостями нужно загрузить вместе, но из-за ложного срабатывания прагмы это обломится.
А какая разница с точки зрения ОДР в одинаковых файлах повторяется определение или в разных?
Любык два поределения объекта, если вообще для таких объектов ОДР допускает, что бы их было больше одного, должны быть ЭКВИВАЛЕНТНЫ жеж?..
Или речь идёт не о С++ объектах, а о препроцессороной магии какой?
К>Может быть, это даже не магия с именами, а скелет плагина К>
К>// plugin_all.h
К>#pragma once
К>#include"./plugin_class.h"
К>#include"./plugin_factory.h"
К>#include"./plugin_tests.h"
К>
К>где в зависимостях уже будут лежать class foo_plugin, class foo_factory и т.д.
Ну это ты ССЗБ, IMHO, это довольно опасная идея, класть в разные места файлы с одним именем, и при этом гарантированно неэквивалентным содержимым. Фиг его знает что откуда подключат
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>А #pragma once в стандарте есть?
Не а.
16.6 Pragma directive [cpp.pragma]
1
A preprocessing directive of the form
# pragma pp-tokens opt new-line
causes the implementation to behave in an implementation-defined manner. The behavior might cause
translation to fail or cause the translator or the resulting program to behave in a non-conforming manner.
Any pragma that is not recognized by the implementation is ignored.
Это все что есть про прагму.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Здравствуйте, Erop, Вы писали:
E>>>Но gcc со своим подходом всё равно козлы! К>>не козлы, а бараны. E>Мне кажется, что в данном случае речь иджёт о ГМО, сочетающем свойства обеих видов E>Я так думаю, что придумали они это сдуру, а внедрили и сохраняют потому, что нетривильный вендор-лок
Что за вендор-лок?
E>Любык два поределения объекта, если вообще для таких объектов ОДР допускает, что бы их было больше одного, должны быть ЭКВИВАЛЕНТНЫ жеж?.. E>Или речь идёт не о С++ объектах, а о препроцессороной магии какой?
О препроцессорной, и даже не магии, а макро-файлах.
Да, это ССЗБ, но приём известный.
Здравствуйте, Кодт, Вы писали:
К>Что за вендор-лок?
Ну если у тебя код адаптирован под такое поведение, то на другой компилятор фиг переедешь без загадочных глюков, правда верно и обратное...
Короче, хочешь заюзать кросплатформенность гцц -- разрабатывай на нём и никакх тебе альетрантивных вендеров...
К>Да, это ССЗБ, но приём известный.
Дык в С/С++ мире грабель известных конструкций ещё больше, чем известных систем для стрельбы по ногам
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
К>Если коротко: gcc для #pragma once использует не путь к файлу, а его атрибуты (размер и время) и содержимое. К>Это он так борется с проблемой алиасов.
А почему не inode? (а под виндой есть fileid)
Как много веселых ребят, и все делают велосипед...
Дык подмапировать могут чегой-нибудь рассово-чуждое и привет...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
O>>А почему не inode? (а под виндой есть fileid) E>Дык подмапировать могут чегой-нибудь рассово-чуждое и привет...
Для рассово-чуждых можно хэшировать файл целиком, сравнив предварительно путь на не-совпадение.
Но, я так понимаю, любители сфероидальных архитектур не обращают внимания на жалобы жителей домов на то, что их жилища постоянно катаются по улицам, что приводит к различным неудобствам. Зато — идеальная сфера.
Как много веселых ребят, и все делают велосипед...