2016-06-03 5 views
1

내가 어떻게 자동으로 전화를 내 CPP 파일에서이자동으로 처리기를 글로벌 맵에 추가하는 방법은 무엇입니까?

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

같은 핸들러 CPP 파일을 많이 만들려면 응용 프로그램 싱글 느릅 나무는 방법을

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

을 가지고 있나요?

내가

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

를 사용하는 것보다 bool addHandlervoid addHandler에서 변경하려고하지만 그것은 작동하지 않았다 저

Udate 그것은 지금 작동하지만, 그것은 더 나은에서 수행 할 수 방법, 사용하지 않고 bool 변수?

+4

마지막 코드가 왜 효과가 없었습니까? – rodrigo

+0

사실 지금은 작동합니다. 모든 핸들러를 정적 라이브러리로 컴파일 한 다음 main.cpp와 링크했습니다. main.cpp로 처리기를 컴파일했을 때 효과가있었습니다. 하지만 더 좋은 방법이 있을까요? 사용하지 않은 변수가 없습니다. –

답변

2

정적 클래스 인스턴스화를 사용합니다.

가짜 코드 - 등록자 클래스를 추가하십시오.

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

또한 익명의 네임 스페이스가 정적'namespace {Registrator test_cpp_reg (........); }' –

+0

@SergeyKolesov 나는 완전히 익명의 네임 스페이스를 가지고있다 :) – Arunmu

1

을 전하려면 addHandler()는 부울을 반환해야한다고 가정? 그렇지 않으면 bool 변수에 할당 할 수 없습니다.

addHandler의 bool 리턴을 제거하려면 정적으로 인스턴스를 생성 한 다른 클래스의 생성자에서 호출을 작성하십시오.

이 종류의 코드는 작동하지만 까다 롭습니다. 문제는 C/C++에서 정적 저장소 초기화 프로그램의 순서가 정의되지 않는다는 것입니다. 따라서 정적 초기화 프로그램이 코드를 호출 할 수있는 동안 해당 코드가 아직 초기화되지 않은 데이터를 참조하면 실패합니다. 그리고 불행하게도 그 실패는 비 결정적입니다. 그것은 잠시 동안 작동 할 수 있습니다, 그리고 당신은 일부 컴파일러 플래그 또는 모듈 순서를 변경하고 splat!

멍청한 포인터를 사용하여 getInstance()의 인스턴스 상태를 구현하는 방법 중 하나는 정적 초기화 프로그램이 실행되기 전에 항상 0으로 초기화되기 때문입니다. 예를 들어 다음 코드는 기본 시작 전에 "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; 
} 
+0

getInstance(),'return bool'을 사용하여 Application에 접근하는 질문에서 볼 수 있듯이 정적 초기화를 사용하여'addHandler'를 호출하는 것만으로도 충분하다. 그러한 해킹없이 더 좋은 방법을 찾으려면 –

+0

예, 내 응답에 다음과 같이 나타납니다 : "addHandler()가 bool을 반환한다고 가정하십시오. 그렇지 않으면 bool 변수에 할당 할 수 없습니다. addHandler가 리턴되면 (자), 정적으로 인스턴스를 생성 한 다른 클래스의 constructor으로부터 호출합니다."나는 아직도 그러나 할 – Wheezil

+0

당신의 getInstance()의 구현을 공유시겠습니까. 정적 초기화에 대해주의? 아니면 프레임 워크에 의해 제공됩니다? 정적 – Wheezil

관련 문제