Можно ли использовать глобальную статическую инициализацию для приложения в стиле «busybox»? - PullRequest
1 голос
/ 10 декабря 2010

Все еще работая над моим гибридом с закрытым / открытым исходным кодом, о котором мы говорили ранее в , этот вопрос .Рассматриваемое приложение на самом деле представляет собой приложение типа «занятый ящик» - несколько программ объединены в одну программу, и фактический запуск программы выбирается на основе первой введенной команды.Это позволяет подпрограммам совместно использовать одну копию CRT (я не могу использовать устанавливаемый redist, потому что мне нужно поддерживать единое двоичное развертывание), а также несколько внутренних компонентов, которые полезны в нескольких подпрограммах.

Поскольку некоторые из самих подпрограмм не могут быть выпущены из-за лицензионных ограничений, я подумываю использовать такой запуск.(Извините за количество кода :()

ISubProgram.hpp

#include <string>
struct ISubProgram
{
    virtual std::wstring GetExecutive() const = 0; //Return sub program name
    virtual void OnStart(int argc, const char *argv[]) {};
    virtual int Run(int argc, const char *argv[]) = 0;
    virtual ~ISubProgram() {}
};

SubProgramList.hpp

#include <memory>
#include <boost/ptr_container/ptr_map.hpp>
#include <boost/noncopyable.hpp>
#include "ISubProgram.hpp"

class SubProgramList;
SubProgramList& GetSubProgramList();

class SubProgramList : boost::noncopyable
{
    friend SubProgramList& GetSubProgramList();
    SubProgramList() {} //Disallow direct creation.
    boost::ptr_map<std::wstring,ISubProgram> programs;
public:
    void RegisterProgram(std::auto_ptr<ISubProgram> subProgramToRegister);
    ISubProgram * FindProgramFromExecutive(const std::wstring& executive);
    void CallOnStartMethods(int argc, char *argv[]);
};

template <typename T>
struct RegisterSubProgram
{
    RegisterSubProgram()
    {
        std::auto_ptr<ISubProgram> toAdd(new T);
        GetSubProgramList().RegisterProgram(toAdd);
    }
}

SubProgramList.cpp

SubProgramList& GetSubProgramList()
{
    static SubProgramList theList;
    return theList;
}

//Implementations of the class methods

ExampleSubProgram.cpp

#include "SubProgramList.hpp"

struct ExampleSubProgram : public ISubProgram
{
    virtual std::wstring GetExecutive()
    {
        return L"ExampleSubProgram";
    }
    virtual int Run(int argc, const char *argv[])
    {
        //Run this program :)
    }
};

namespace { RegisterSubProgram<ExampleSubProgram> registrar; }

Main.cpp

#include "SubProgramList.hpp"

int main(int argc, char *argv[])
{
    SubProgramList& list = GetSubProgramList();
    list.CallOnStartMethods(argc, argv);
    std::wstring subProgramName(/*.. Generate from argv[1] ...*/);
    FindProgramFromExecutive(subProgramName)->Run(argc, argv);
}

I думаю Я свободен от проблем порядка инициализации, потому что единственным глобальным состоянием является локальное состояниестатический, а не глобальный статический.

Основная причина этого заключается в том, что я могу полностью разделить биты программы с закрытым и открытым исходным кодом программы, что сделает объединение быстрым и эффективным, а также удалит шаблонмой текущий «Выбор подпрограммы Giant if / else» в main.

Является ли это разумным использованием инициализации при запуске (что обычно не рекомендуется?) Если нет, какую альтернативную реализацию вы бы предложили?

1 Ответ

2 голосов
/ 10 декабря 2010

Я мог бы придумать несколько умных программ с рекурсивным созданием шаблона, но реальность такова, что то, что вы сделали, на , вероятно, проще, чем то, что я могу придумать.Редко я полагаю, что глобальное состояние - это разумная идея, но на этом мне, возможно, придется признать, что я не могу добиться большего успеха.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...