Автоматизировать развертывание классов C ++ & # 8212; Есть ли простой способ?
-
06-07-2019 - |
Вопрос
Pimpl являются источником шаблонного кода во многих кодах C ++. Они кажутся такими вещами, которые может решить комбинация макросов, шаблонов и, возможно, небольшая помощь со стороны внешнего инструмента, но я не уверен, каким будет самый простой способ. я видел шаблоны , которые помогают выполнять некоторые операции по подъему, но не так много - вам все равно придется писать функции пересылки для каждого метода класса, который вы пытаетесь обернуть. Есть ли более простой способ?
Я представляю себе инструмент, используемый как часть процесса создания. Вы хотите, чтобы ваши публичные заголовки были классами pimpl'd, поэтому вы предоставляете некоторый входной файл, скажем pimpl.in, в котором перечислены классы (реализованные un-pimpl'd), которые вы хотите обернуть, затем этот файл проверяется, классы pimpl генерируются, и только их заголовки (не заголовки исходного класса) устанавливаются во время 'make install'. Проблема в том, что я не вижу способа сделать это без полноценного синтаксического анализатора C ++, что даже поставщики компиляторов не могут сделать правильно. Может быть, классы могли бы быть написаны так, чтобы упростить работу внешнего инструмента, но я уверен, что в конечном итоге я пропущу все виды угловых случаев (например, шаблонные классы и / или шаблонные функции-члены).
Есть идеи? Кто-нибудь еще пришел с решением этой проблемы?
Решение
Нет, простого ответа нет. :-( Я думаю, что почти каждый эксперт по ОО говорит: «предпочитаю композицию наследованию», была бы языковая поддержка, чтобы сделать композицию намного проще, чем наследование.
Другие советы
Я не говорю, что это хорошо (просто то, что пришло в голову).
Но вы можете поэкспериментировать с перегрузкой оператора - >
#include <memory>
#include <iostream>
class X
{
public:
void plop()
{
std::cout << "Plop\n";
}
};
class PimplX
{
public:
PimplX()
{
pimpl.reset(new X);
}
X* operator->()
{
return pimpl.get();
}
private:
PimplX(PimplX const&);
PimplX& operator=(PimplX const&);
std::auto_ptr<X> pimpl;
};
int main()
{
PimplX x;
x->plop();
}
Один из вариантов - использовать интерфейсный класс:
class ClassA {
virtual void foo() = 0;
static ClassA *create();
};
// in ClassA.cpp
class ImplA : public ClassA {
/* ... */
};
ClassA *ClassA::create() {
return new ImplA();
}
Это, однако, увеличивает издержки при получении указателей на функции vtable.
Кроме этого, я не могу думать ни о каком таком инструменте. Как вы сказали, синтаксический анализ C ++ является нетривиальным, и есть другие языки, в которых это не представляет особой проблемы (например, C # или Java с поздним связыванием всего, так что вы можете изменить их расположение в памяти позже без проблем). р>