2013-07-19 2 views
1

다음 템플릿 정의는함수 포인터 및 함수 객체를 일반 코드로 묶는 방법은 무엇입니까?

template <typename Func, typename ReturnType, typename... Arguments> 
class Command 
{ 
public: 
    Command(Func f) : m_func(f) { } 
    ReturnType operator()(Arguments... funcArgs) { return m_func(funcArgs...); } 
private: 
    Func m_func; 
}; 

에 오류 메시지를 제공 GCC 4.7.3 (오류 : 필드 '명령 :: m_func'을 잘못 선언 된 함수 타입) 다음과 같은 테스트 코드로 인스턴스화 :

void testFunction(int i, double d) 
{ 
    std::cout << "TestFunctor::operator()(" << i << ", " << d << ") called." << std::endl; 
} 

int main() 
{ 
    void (&fRef)(int, double) = TestFunction; 
    Command<void(int, double), void, int, double> testCommand(fRef); 
} 

또한 오류 메시지는 주소 연산자가없는 TestFunction을 testCommand 생성자에 전달할 때 발생하지만 명시 적으로 명명 된 함수 포인터를 전달하거나 주소 연산자를 사용하여 매개 변수를 전달하면 사라집니다. 나는이 코드가 Modern C++ Design의 Chapter 5에서 주어진대로 동작해야한다고 생각합니다.

함수에 대한 참조를 저장할 수없는 이유는 무엇입니까?하지만 함수 포인터는 정상적으로 작동합니까? 펑터를 Command의 생성자에 인수로 전달할 수 있다는 지원을 잃지 않고 컴파일 할 수있는 해결 방법이 있습니까?

답변

5

이 문제를 해결할 수있는 하나 개의 라인 변경을 함수 유형 대신 함수 포인터를 전달하고 있습니다. (함수는 복사 할 수 없지만 포인터는 있습니다).

참조 번호 fRef전달할 때 함수 포인터에 대한 참조 번호는입니다.

성능이 중요한 경우 std::function을 사용하지 않을 것을 제안합니다.

int main() 
{ 
    auto command = make_command(testFunction); 
    command(1, 3.14); 
} 

이를 위해, 나는 Command 템플릿을 변경하는 게 좋을 것 것은 수 :

약간의 재 작성으로, 당신은 모든 것이 훨씬 좋네요 작동하게 할 수는 live on Coliru

참고 참조 :

template <typename Func> 
class Command 
{ 
    Func m_func; 
public: 
    Command(Func f) : m_func(f) { } 

    template <typename... A> auto operator()(A... args) const 
     -> decltype(m_func(args...)) 
    { return m_func(args...); } 
}; 

그리고 지금 당신은 Func 템플릿 PA에 형식 공제를 할 수 있습니다 공장 기능을함으로써 rameter :

template <typename Func> Command<Func> make_command(Func f) 
{ 
    return Command<Func>(f); 
} 

이 방법 live on Coliru도를 참조하십시오. 물론 출력은 동일합니다 :

TestFunctor::operator()(1, 3.14) called. 
2

C++ 11은 std::function 템플릿을 제공합니다. 함수 포인터를 망칠 필요가 없습니다.

당신은 그들을 참조하여 사람들을 복사 통과로 이동하고 그들은 심지어 람다 저장하는 데 사용할 수 있습니다 :

Command<void(*)(int, double), void, int, double> testCommand(fRef); 

의 차이는 다음과 같습니다

std::function<void()> func = []() { std::cout << "Hi" << std::endl; };