Я хочу исключить некоторые заголовки из моей цепочки включения после их использования. Из того, что я знаю, нет исключения «header.h» в c ++ 11.
Псевдокод Желаемое за действительное:
#include "the_bad_header.h" //long includechain with later unused declarations
class bulky { ... };
constexpr std::size_t bulkysize = sizeof(bulky);
forget everything included and class bulky and remember only bulkysize
Вот мой пример, где проблема становится очевидной. Пожалуйста, не спорьте, это не серьезная проблема. Пример разбит на части, чтобы показать минимальное использование абстрактного языка. Я опишу старомодные решения и их недостатки тоже.
justanotherheader.h:
class bulkywrap
{
public:
bulkywrap();
protected:
friend class bulkywrap_pImpl;
bulkywrap_pImpl *const pImpl; //opaque pointer, private implementation
};
justanothercppunit.cpp:
#include "justanotherheader.h"#include "boost/lotsofheaders.hpp"//#include more and more headers of highly complex libraries so adding millions of known types and other identifiers, macros, and so on
class bulkywrap_pImpl
{
//lots of members of types used from the other libraries
};
bulkywrap::bulkywrap()
: pImpl( new bulkywrap_pImpl() )
{}
justanotherheader.h:
#include "stdint.h" // this is the only header I like to use, but also unnecessary.
#define UNKNOWNSIZE 12345
class bulkywrap
{
public:
bulkywrap();
protected:
friend class bulkywrap_pImpl;
bulkywrap_pImpl *const pImpl; //opaque pointer, private implementation
uint8_t pImpl_Placement[UNKNOWNSIZE]; //placement new for pImpl
};
justanothercppunit.cpp:
#include "justanotherheader.h"#include "boost/lotsofheaders.hpp"//#include more and more headers of highly complex libraries so adding millions of known types and other identifiers, macros, and so on
class bulkywrap_pImpl
{
//lots of members of types used from the other libraries
};
bulkywrap::bulkywrap()
: pImpl( new(this->pImpl_Placement) bulkywrap_pImpl() ) //using this here is safe
{}
Итак, приведенный выше код работает. Преимущества: скрытие сложности и отсутствие динамических косвенных обращений к памяти. А? Я имею в виду, что размещение new позволяет поместить весь объект в стек, а все адреса членов известны во время компиляции. Я пытаюсь добиться максимальной производительности при использовании дизайна интерфейса непрозрачного указателя.
Если вы думаете: «это преимущество в производительности не стоит мыслительных усилий». тогда, пожалуйста, оставьте этот вопрос.
justanotherheader.h:
#include "stdint.h" // this is the only header I like to use, but also unnecessary.
constexpr std::size_t get_bulkywrap_pImpl_Size( void ); //constexpr function forward declaration
extern constexpr std::size_t bulkywrap_pImpl_Size; //constexpr literal forward declaration with external initialization
class bulkywrap
{
public:
bulkywrap();
protected:
friend class bulkywrap_pImpl;
bulkywrap_pImpl *const pImpl; //opaque pointer, private implementation
uint8_t pImpl_Placement[get_bulkywrap_pImpl_Size()]; //undefined constexpr used
uint8_t pImpl_Placement[bulkywrap_pImpl_Size]; //alternative to above. undefined constexpr used
};
justanothercppunit.cpp:
#include "justanotherheader.h"#include "boost/lotsofheaders.hpp"//#include more and more headers of highly complex libraries so adding millions of known types and other identifiers, macros, and so on
class bulkywrap_pImpl
{
//lots of members of types used from the other libraries
};
constexpr std::size_t get_bulkywrap_pImpl_Size( void )
{
return sizeof(bulkywrap_pImpl);
}
constexpr std::size_t bulkywrap_pImpl_Size = sizeof(bulkywrap_pImpl);
bulkywrap::bulkywrap()
: pImpl( new(this->pImpl_Placement) bulkywrap_pImpl() ) //using this here is safe
{}
В моем текущем решении мне нужно проверить sizeof (bulkywrap_pImpl) и вручную настроить UNKNOWNSIZE.
Я думаю, что в настоящее время невозможно получить какую-либо информацию из сборника для других. Я знаю, что это, как правило, имеет под собой веские основания, но это ограничивает возможности c ++ 11.
Я хочу отметить:
Пожалуйста, помогите мне найти информацию о погоде и почему стандарт не позволяет этого.
Но, кроме того, я хотел бы найти решение о том, как экспортировать некоторую буквальную константу во время компиляции из компиляции в другую компиляцию. Это просто литерал, поэтому он не влияет на все утверждения и выражения. Таким образом, компиляция не зависит от размера массива.
Мое предложение приводит к некоторой работе для ISO-jtc1-sc22-wg21 и разработчиков компилятора, но я не вижу какой-либо существенной разницы между шаблоном и constexpr, поскольку каждое определение должно появляться в одном и том же переводческом модуле. Это делает модульное программирование и чистые интерфейсы поддельными.
И нет: я не хочу использовать макросы препроцессора, динамические новые или виртуальные функции-члены. Важна максимальная константность, поскольку размер класса является константным.
Пожалуйста помоги
вы не можете иметь одновременно «время компиляции» и «из другого модуля компиляции». Также непонятно, зачем вам забывать успешно разобранный заголовок. время разбора уже потрачено. я предлагаю вам создать еще один заголовок с константой размера, включить его из обоих файлов и добавить static_assert в файл pimpl, проверив, что constant >= sizeof(pimpl)
, Вы можете сгенерировать этот заголовок как часть вашей системы сборки, скомпилировав исходный файл, включая pimpl и выполнив cout <<sizeof(pimpl)
, Также я предлагаю вам не тратить время и пространство на указатель pimpl и заменить его функцией-членом, возвращая адрес правильно приведенного буфера. также вы не смогли показать, где вы называете деструктором pimpl. также реализация назначения / копирования / перемещения / обмена будет очень интересной
используйте static_assert в cpp, чтобы проверить, что размер объявлен в заголовке> = размер класса impl