соратника шахты регулярно использует вариацию на Pimpl, что он делает так:pimpl idiom с использованием структуры анонимного пространства имен: это безопасно?
foo.h:
namespace { struct Impl; }
class Foo
{
public:
Foo();
~Foo();
void Bar(int n);
/* ... */
private:
std::unique_ptr<Impl> _impl;
};
То, что здесь происходит, что он вперед объявить класс реализации, чтобы быть в анонимное пространство имен. Затем он определит класс Impl
внутри Foo.cpp.
Таким образом, определение структуры ::Impl
будет доступно для единицы перевода Foo.cpp
. Другой код включает Foo.h
, будет предупреждать, потому что они явно не могут получить доступ к ::Impl
, указанному в Foo.cpp
. Но тогда нам они не нужны - это класс, предназначенный для использования только в Foo.cpp
; мы не хотите это видно или известно в другом месте.
И в то время как мы можем, конечно, есть ситуации, когда на .cpp
файла, включая несколько заголовков, каждый из которых объявляя свои собственные ::Impl
структуры, они фактически не конфликтует, потому что структуры никогда не используются за пределами их соответствующих единиц перевода.
tl; dr: Это выглядит странно, вызывает предупреждения и выглядит так, как будто это может вызвать столкновения, но, похоже, на самом деле работает.
Все, что было сказано, я не комфортно с того, что возвышает предупреждения запеченные так глубоко в наш код (больше заголовков файлов это находится, тем труднее будет вынуть). Это также только тонна предупреждений.
Мой товарищ по команде стоит на этом, потому что он прост, содержит простые определения кода и позволяет использовать короткий, согласованный класс Impl
по всему нашему коду.
Я не сторонник кодирования условностей; если это хорошая практика для нашего прецедента, я не против. Но я хотел бы чувствовать себя комфортно, что это безопасно и легко обслуживается, и в какой-то момент он не будет взорваться в наших лицах.
Точка зрения, я * думаю *, что нет ':: Impl'. Использование ':: Impl' пытается получить доступ к символу' Impl' в * глобальном * пространстве имен, но оно не входит в глобальное пространство имен. Другой распространенный способ - сделать структуру 'Impl' частным членом самого класса. –
Если это происходит в файле заголовка, который используется несколькими единицами перевода, я думаю, что это нарушение ODR. Каждое анонимное пространство имен отличается в каждой единицы перевода, поэтому класс Foo не будет иметь согласованного определения во всех единицах перевода. –
См. Http://stackoverflow.com/a/23653494/951890 –