в общем случае никак, но если неймспейс как-то учитывает файловую иерархию, то шанс таких ошибок как правило меньше
Есть анонимные нэймспейсы. Не уверен конечно, что сильно поможет. Разве что компайл тайм ошибка будет если два заголовка с одинаковыми объектами в один ТУ подключите
Тут не анонимный нейсмспейс нужен, а с одинаковым, но уникальным именем во всех включениях хедера
Анонимные неймспейсы фактически не работают в хедерах. namespace { int i; } будет создавать в каждом tu свой i. Теоретически в некоторых случаях, они действительно могут решить проблему с odr в хедерах, но я не на столько смелый. =)
Кажется, единственное рабочее решение — один раз в определении добавить inline namespace со случайным именем
Да, кажется, работает. Мне вчера по формулировкам из стандарта показалось, что не должно, но формулировки odr я плохо знаю. Спасибо, попробую.
Сборка с LTO не помогает в этом случае? Ещё мне пришло в голову, что простейшие случаи мог бы ловить Doxygen, но он, увы, просто игнорирует такие ситуации
Для меня идеальным вариантом было бы сохранить короткие удобные имена, которые могут клашиться. Кажется что inline namespace частично позволяет это, но да, такое решение не будет масштабироваться и его нельзя выставлять в публичный интерфейс. Моя текущая мысль состоит в том, чтобы использовать обычный неймспейс, но нужно научится генерировать препроцессором уникальный id на уровне файла: #define DETAILS // generate unique id namespace DETAILS { void foo(); } void bar() { DETAILS::foo(); }
>> научится генерировать препроцессором уникальный id на уровне файла Боюсь, что это очень тернистый путь, даже сами компиляторы уникальные имена для анонимных неймспейсов научились генерировать далеко не сразу
С inline namespace проще же #define UNIQ // generate unique id namespace detail { inline namespace UNIQ { void foo(); }} void bar() { detail::foo(); }
А ты уверен, что оно правильно работать будет и не будет генерировать два уникальных айди?
Проблема в том, что // a.h namespace detail { inline namespace UNIQ_123 { void foo(); }} void bar() { detail::foo(); } // b.h namespace detail { inline namespace UNIQ_456 { void foo(); }} void baz() { detail::foo(); } // cpp #include <a.h> #include <b.h> int main() { bar(); baz(); } приведет к конфликту.
Да, но кажется что даже строя id на имени файла уже можно серьезно уменьшить шансы конфликта.
Ну тут другого рода конфликт, все-таки Без uniq можно получить нарушение ODR, которое красиво взорвется в рантайме
В моем снипете DETAILS - это и есть UNIQ. Фактически inline не дает преимуществ по сравнению с использованием просто namespace UNIQ.
Будет уникальное имя только в одном месте, а не по всему хедеру, но не больше, да
Да, кажется что в препроцессоре нельзя преобразовать строку в токен. Без этого я не знаю как получить идентификатор стабильный на уровне файла, а не TU. Передавать снаружи идентификаторы нельзя по той же причине: нужна уникальность на уровне файла, а не TU. В теории рефлексия может помочь, но к ее приходу уже, наверное, можно будет пользоваться модулями. =(
Только токен в строку.
А какая проблема решается? Возникают конфликты при single compilation unit?
Был clang-плагин, который сам генерировал аналог этих UNIQ_xxx и ещё подставлял в символы использование именно этого UNIQ_xxx. Это было сделано для анонимных неймспейсов для single compilation unit, но здесь похожая проблема как вижу
Это я так прокрастинирую. -_- Формально проблема описана здесь.
Плагин это интересно, но все же переносимость мне важнее.
Обсуждают сегодня