Здравствуйте, Constructor, Вы писали:
BFE>>Есть подводные камни у такого решения? C>Пробовали ли Вы скомпилировать это решение?
Да, конечно. Но может надо пояснить, что компиляция того или иного *.cpp определяется с помощью define'а. Меня интересует насколько безопасно помещать namespace { class A_impl; } в хедере.
Здравствуйте, B0FEE664, Вы писали:
BFE>Здравствуйте, Constructor, Вы писали:
BFE>>>Есть подводные камни у такого решения? C>>Пробовали ли Вы скомпилировать это решение?
BFE>Да, конечно.
В таком случае Вы пользуетесь компилятором, который не соответствует стандарту. Каждое безымянное пространство имен уникально, поэтому подобный код компилироваться не должен (класс A [ A_impl в вашем случае] так и останется неполным типом, поскольку его "определение" — это всего лишь объявление другого класса с таким же именем в другом пространстве имен):
namespace
{
class A;
}
namespace
{
class B
{
A a;
};
}
namespace
{
class A
{
};
}
int main()
{
}
Здравствуйте, Constructor, Вы писали:
C>В таком случае Вы пользуетесь компилятором, который не соответствует стандарту. Каждое безымянное пространство имен уникально,
Оно ведь уникально для единицы трансляции, а не для каждого упоминания?
C>поэтому подобный код компилироваться не должен (класс A [ A_impl в вашем случае] так и останется неполным типом, поскольку его "определение" — это всего лишь объявление другого класса с таким же именем в другом пространстве имен):
Здравствуйте, B0FEE664, Вы писали:
C>>В таком случае Вы пользуетесь компилятором, который не соответствует стандарту. Каждое безымянное пространство имен уникально, BFE>Оно ведь уникально для единицы трансляции, а не для каждого упоминания?
Да, прошу прощения, перепутал.
C>>поэтому подобный код компилироваться не должен (класс A [ A_impl в вашем случае] так и останется неполным типом, поскольку его "определение" — это всего лишь объявление другого класса с таким же именем в другом пространстве имен):
BFE>Pimpl это указатель прежде всего, сейчас поправлю исходное сообщение.
Да, у Вас все правильно, вроде бы.
Но вместо
namespace {
class A_impl;
}
class A
{
.....
void f();
private:
A_impl* m_pimpl;
};
можно просто написать
class A
{
.....
void f();
private:
class A_impl* m_pimpl;
};
Здравствуйте, tdiff, Вы писали:
BFE>>Оно ведь уникально для единицы трансляции, а не для каждого упоминания? T>Ок, а это не нарушает ODR? T>В TU пользователя класса A и в TU a_impl1.cpp будут разные определения класса A.
И они будут лежать в разных namespace'ах, насколько я понимаю.
Здравствуйте, B0FEE664, Вы писали:
T>>В TU пользователя класса A и в TU a_impl1.cpp будут разные определения класса A.
BFE>И они будут лежать в разных namespace'ах, насколько я понимаю.
класс A будет лежать в глобальном неймспейсе, но в TU пользователя класса A будет одно определение класса, а в a_impl1.cpp будет второе. как следствие — UB
если ты ограничишь использование класса A таким образом, что a.hpp будет инклюдиться только в в один cpp (например, a_impl1.cpp), то нарушения ODR уже не будет
вообще, есть замечательная рекомендация — избегайте анонимных неймспейсов в .hpp
Здравствуйте, enji, Вы писали:
E>Нарушает по идее, но пользователь то видит только указатель. Имхо, врядли будут проблемы.
компиляторы сейчас более агрессивно себя ведут и используют UB, как уважительную причину для своих фейлов оптимизации
Здравствуйте, sokel, Вы писали:
S>Ну или голый void*, если конструкторы суровые и не лень касты писать
А для удобства можно в том же unnamed namespace касты подсократить:
Здравствуйте, uzhas, Вы писали:
T>>>В TU пользователя класса A и в TU a_impl1.cpp будут разные определения класса A. BFE>>И они будут лежать в разных namespace'ах, насколько я понимаю. U>класс A будет лежать в глобальном неймспейсе, но в TU пользователя класса A будет одно определение класса, а в a_impl1.cpp будет второе. как следствие — UB