如何自动将处理程序添加到全局地图?

时间:2016-06-03 13:15:32

标签: c++ c++11

我有应用程序单例,它有方法

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变量吗?

2 个答案:

答案 0 :(得分:2)

使用静态类实例化。

伪代码 - 添加一个registrator类。

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();
});

答案 1 :(得分:1)

我认为addHandler()应该返回bool?否则,您无法分配给bool变量。

要删除addHandler的bool返回,请从静态实例化的其他类的构造函数中调用。

这种代码可以工作,但很棘手。问题是在C / C ++中,静态存储初始化器的顺序是未定义的。因此,虽然允许静态初始化程序调用任何代码,但如果该代码引用尚未初始化的数据,则它将失败。不幸的是,失败是不确定的。它可能会工作一段时间,然后你改变一些编译器标志或模块顺序,并splat!

一个技巧是使用哑指针实现getInstance()的实例状态,因为在任何静态初始化程序触发之前,它总是初始化为零(null)。例如,以下代码将在主要启动之前打印“Added 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;
}