2014-12-11 1 views
0

여러 tr1 :: 함수를 저장하고 호출 할 수있는 일반 개체를 만들고 싶습니다.일반 옵션 매개 변수

지금까지, 나는

typedef tr1::function<void (SomeObject)> SomeFunction; 

이 작동

vector<SomeFunction> functionStorage 

같은 개체의 멤버 필드에 저장하는 타입 정의 및 벡터를 사용,하지만 난에 대한 코드를 복제 할 필요가 모든 객체에서 함수를 추가하고 호출합니다. 그래서 좀 더 일반적인 해결책을 찾으려고 노력했습니다. 이상적으로, 내가 직접

template<typename T> 
class FunctionStore 
{ 
    public: 
     FunctionStore<T>(); 
     virtual ~FunctionStore<T>(); 

     void addFunction(const T &newFunction); 
     void callAllFunctions(const Parameter & parameter) const; 
    private: 
     vector<T> functionStorage; 
}; 

등 모두 반환 형식과 매개 변수 유형을 포함, 함수 형식 정의를 전달할 수 있습니다하지만 난 내에서 밖으로 매개 변수 목록을 얻을 수 있기 때문에이 작동하지 않은 일부 템플릿 객체를 원했다 템플릿은 callAllFunctions 함수를 올바르게 정의해야합니다.

:

나는 다음하지만 매개 변수의 고정 번호가 제대로 전체 TR1 :: 기능을 typedeffing 그냥 클래스 자체, 작품의 종류 내에서 returnType이와 parameterType로이 분할에 대한 옵션을 무시하려
template<typename R = void, typename P1 = void> 
class FunctionStore 
{ 
     typedef tr1::function<R(P1 &)> Function; 

    public: 
     FunctionStore<R, P1>(); 
     virtual ~FunctionStore(); 

     void addFunction(const Function &newFunction) 
     { 
      functionStorage.push_back(newFunction); 
     } 

     void callAllFunctions(const P1 &parameter) const 
     { 
      for(Function fn : functionStorage) 
      { 
       fn(parameter); 
      } 
     } 

    private: 
     vector<Function> functionStorage; 
}; 

하지만 이걸로는 P1 유형을 선택적으로 만들 수 없습니다. 나는 이것을 기본값으로 void로 시도했지만, P1 & parameter으로 사용하기 때문에, fn(void &)을 예상하는 것으로 평가할 것이다. 이것은 fn()과 같지 않다. 또한 &을 사용하지 않으면 불법적 인 void 참조가 만들어지기 때문에 작동하지 않습니다. 또한 변수 요구 사항을 해결할 수 있기 때문에 variadic 매개 변수에 대해 생각했지만 매개 변수 개수와 형식이 분명히 유형에 분명히 정의되어 있으므로 (tr1 :: bind placeholder stuff에 필요함) 잘못된 방식 인 것 같습니다. 가다.

그래서 어떻게해야합니까? 첫 번째 옵션을 만들 수있는 실제 방법이 없다고 가정합니다. 두 번째 옵션에 대한 솔루션은 여전히 ​​많은 도움이됩니다. C++ (11)와 가변 인자 템플릿으로

+0

C++ 11에 액세스 할 수 있습니까? 나는 추정하지 않는다. – Yakk

+0

글쎄, 이것도 Windows에서 실행되어야하므로, 나는 C++ 0x와 함께 minGW의 GCC4.7을 컴파일한다. 그래서 기본적으로 C++ 11이지만 함수 같은 것들은 여전히 ​​tr1에있다. 단순함을 위해서, C++ 11로 가정하자 .. – DragonTEC

답변

0

, 당신은 할 수 있습니다

template<typename R = void, typename... Args> 
class FunctionStore 
{ 
     typedef tr1::function<R(const Args&)> Function; 

    public: 
     FunctionStore<R, P1>(); 
     virtual ~FunctionStore(); 

     void addFunction(const Function &newFunction) 
     { 
      functionStorage.push_back(newFunction); 
     } 

     void callAllFunctions(const Args... &parameters) const 
     { 
      for(Function fn : functionStorage) 
      { 
       fn(parameters...); 
      } 
     } 

    private: 
     vector<Function> functionStorage; 
}; 
0

전문화 프로그램을 :

template<class Sig> 
class FunctionStore; 

template<class R, class...Args> 
class FunctionStore<R(Args...)> { 
    typedef std::tr1::function<R(Args...)> Function; 
    public: 
    FunctionStore() {} 
    virtual ~FunctionStore() {} 

    void addFunction(Function f) { 
     functionStorage.emplace_back(std::move(f)); // or push_back on C++03 
    } 

    template<class...Ts> 
    void callAllFunctions(Ts&&... ts) const 
    { 
     for(auto&& fn : functionStorage) { 
     bool last_iteration = &fn == functionStorage.data()+functionStorage.size()-1; 
     if (last_iteration) 
      fn(std::forward<Ts>(ts)...); 
     else 
      fn(ts...); // or remove all the rest of the loop body, and just fn(ts...) 
     } 
    } 
    private: 
    std::vector<Function> functionStorage; 
}; 

지금, last_iteration 아마 너무 많은 마이크로 최적화입니다. 그냥 fn(args...).

위의 코드는 callAllFunctions에 대한 명시적인 인수 대신 완벽한 전달을 사용하며 완벽한 전달은 약간 불완전합니다. 대신 template 매개 변수가없는 callAllFunctions(Args... args) 서명을 만들 수 있습니다. {} 기반 구조 등입니다.

+0

나는 forward, lvalues와 rvalues에 대해 많은 것을 배웠다. 전에는 알지 못했지만 몇 가지 질문이있다. a) 나는 그것이'data() * 크기() - 1)'마지막 반복 검사에서? b) 마지막 반복 분기에서 'ts ...'가되어야한다고 가정합니다.c) 마지막 반복에서 만 완벽한 전달을하고 있으므로 여러 함수 호출이 동일한 rvalues를 사용하지 않습니다. (이것에 대해서는 잘 모르겠습니다. – DragonTEC

+0

또한 내부 템플릿 멤버 함수에 대한 개념을 이해하지 못했습니다. 왜냐하면 궁극적으로 tr1 :: functions을 저장하기 때문에 F는 같은 유형의 구조를 가질 필요가 있기 때문입니다. 이미 Function typedef를 사용했기 때문에 Ts가 Args와 다를 수 있으므로 설계되지 않은 매개 변수를 사용하여 저장된 함수를 호출 할 수 없습니까? tr1을 작성할 수없는 addFunction()과 동일합니다. 함수는 임의의 객체로부터 얻을 수 있습니까? – DragonTEC

+0

@DragonTEC 아니요, 'data()'는 포인터이므로 추가해야합니다 .'F'는'tr1 :: function' 일 필요는 없습니다. 람다, 함수 객체, 함수 포인터 또는'std :: nullptr'처럼'tr1 :: function'을 생성하는데 사용될 수 있습니다. 우리는 간단히'tr1 :: function'과'std :: move'를 취할 수 있습니다. 지금부터 생각해 보겠습니다. 나는 그것을 바꿀 것입니다. 다음으로, 잘못된 매개 변수로 함수를 호출하면 컴파일 타임 오류가 발생합니다. 심지어 템플릿 메서드의 본문에서 발생합니다. 그래서 그것은 잘못된 주장으로 그것을 결코 부르지 않을 것입니다. – Yakk