Автоматизировать развертывание классов C ++ - есть ли простой способ? - PullRequest
11 голосов
/ 25 октября 2009

Pimpl являются источником стандартного кода на C ++. Они кажутся такими вещами, которые может решить комбинация макросов, шаблонов и, возможно, небольшая помощь со стороны внешнего инструмента, но я не уверен, каким будет самый простой способ. Я видел шаблоны , которые помогают выполнять некоторые действия, но не очень - вам все равно придется писать функции пересылки для каждого метода класса, который вы пытаетесь обернуть. Есть ли более простой способ?

Я представляю себе инструмент, используемый как часть процесса создания. Вы хотите, чтобы ваши публичные заголовки были классами pimpl'd, поэтому вы предоставляете некоторый входной файл, скажем pimpl.in, в котором перечислены классы (реализованные un-pimpl'd), которые вы хотите обернуть, затем этот файл проверяется, классы pimpl генерируются и только их заголовки (не заголовки исходного класса) устанавливаются во время 'make install'. Проблема в том, что я не вижу способа сделать это без полноценного синтаксического анализатора C ++, что даже поставщики компиляторов не могут сделать правильно. Может быть, классы могли бы быть написаны так или иначе, что упростит работу внешнего инструмента, но я уверен, что в конечном итоге я пропущу все виды угловых случаев (например, шаблонные классы и / или шаблонные функции-члены).

Есть идеи? Кто-нибудь еще пришел с решением этой проблемы уже?

Ответы [ 3 ]

6 голосов
/ 25 октября 2009

Нет, простого ответа нет. :-( Я думаю, что почти каждый эксперт ОО, говорящий «предпочитаю композицию, а не наследование», будет иметь языковую поддержку, чтобы сделать композицию намного проще, чем наследование.

2 голосов
/ 26 октября 2009

Я не говорю, что это хорошо (просто то, что пришло в голову).
Но вы можете поэкспериментировать с перегрузкой оператора ->

#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();
}
0 голосов
/ 25 октября 2009

Один из вариантов - использовать интерфейсный класс:

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 с поздним связыванием всего, так что вы можете изменить их расположение в памяти позже без проблем).

...