2016-06-03 4 views
1

У меня есть приложения одноточечны которым есть методКак автоматически добавить обработчик на глобальную карту?

void addHandler(const std::string& command, std::function<std::string (const std::string&)> handler) 

Я хочу создать много CPP файлов с обработчиками как этот

//create_user_handler.cpp 
Application::getInstance()->addHandler("create_user", [](std::string name) { 
    UserPtr user = User::create(name); 
    return user->toJson(); 
}); 

Как автоматически вызывать это из моих CPP файлов?

Я стараюсь меняться от void addHandler к bool addHandler и чем использовать

namespace { 
    bool b = Application::getInatance()->addHandler...... 
} 

, но он не работает для меня

Udate Он работает сейчас, но это могло быть сделано лучше путь, без неиспользованной переменной bool?

+4

Почему последний код не работает для вас? – rodrigo

+0

На самом деле он работает сейчас. Я скомпилировал все мои обработчики как статическую библиотеку, а затем связал ее с main.cpp. Когда я только что скомпилировал обработчики с main.cpp, он работал. Но есть ли лучший способ сделать это? Без неиспользуемой переменной. –

ответ

2

Использовать статическую классификацию классов.

Pseudo code - Добавить класс регистратора.

class Registrator { 
    template <typename Func> 
    Registrator(const std::string& name, Func handler) { 
    Application::getInstance()->addHandler(name, handler); 
    } 
}; 

И в каждом файле CPP, создать статический объект класса:

test.cpp 

static Registrator test_cpp_reg("create_user", [](std::string name) { 
    UserPtr user = User::create(name); 
    return user->toJson(); 
}); 
+0

Спасибо, я думаю, это лучший способ сделать это. –

+0

Кроме того, вместо статического пространства имен можно использовать анонимные пространства имен {Registrator test_cpp_reg (........); } ' –

+0

@SergeyKolesov Я полностью передаю анонимное пространство имен :) – Arunmu

1

Я предполагаю, что ДобавитьОбработчик() должен возвращать логическое значение? В противном случае вы не можете назначить переменную bool.

Чтобы удалить bool return addHandler, сделайте вызов от конструктора другого класса, который вы, в свою очередь, создаете статически.

Этот вид кода может работать, но это сложно. Проблема в том, что в C/C++ порядок инициализаторов статического хранилища не определен. Таким образом, хотя статическому инициализатору позволено вызывать любой код, если этот код ссылается на еще неинициализированные данные, он будет терпеть неудачу. И, к сожалению, неудача является недетерминированной. Он может работать некоторое время, а затем вы меняете какой-то флаг компилятора или порядок модулей и splat!

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

#include <string> 
#include <functional> 
#include <map> 
#include <iostream> 

class Application { 
public: 
    static Application* getInstance() { 
     // Not thread-safe! 
     if (instance == 0) { 
      instance = new Application; 
     } 
     return instance; 
    } 
    typedef std::function<std::string(const std::string&)> HANDLER; 
    typedef std::map<std::string, HANDLER> HANDLER_MAP; 
    bool addHandler(const std::string& command, HANDLER handler) { 
     handlerMap.insert(HANDLER_MAP::value_type(command, handler)); 
     std::cout << "Added " << command << "\n"; 
     return true; 
    } 
    HANDLER_MAP handlerMap; 
    static Application* instance; 
}; 
Application* Application::instance; 

std::string myHandler(const std::string&) { return ""; } 
bool b = Application::getInstance()->addHandler("foo", myHandler); 

int main() 
{ 
    return 0; 
} 
+0

Как вы можете видеть в вопросе, я получаю доступ к Приложению, используя getInstance(),' return bool', это всего лишь трюк, чтобы вызвать 'addHandler', используя статическую инициализацию, и я просто хочу найти лучший способ сделать это без таких хаков –

+0

Да, вы заметите в моем ответе: «Предположим, что addHandler() должен возвращать bool? В противном случае вы не можете назначить переменную bool. Чтобы удалить bool return addHandler, сделать вызов от конструктора какого-либо другого класса, который вы, в свою очередь, создаете статически." – Wheezil

+0

Однако я все еще предостеречь вас о статических инициализаторах. Не хочешь ли поделиться своим осуществлением GetInstance()? Или он поставляется в рамках? – Wheezil

Смежные вопросы