2012-12-10 3 views
6

이 질문은 이전에 물어 보았지만 꽤 경험있는 코더 임에도 불구하고 나는 대답을 이해하지 못하고 이러한 이전 질문에 응답 할 방법이 없다고 생각합니다. 설명. "답장"링크 또는 기타 사항이 없습니다. 게다가, 그 질문은 꽤 오래되었습니다. 그래서, 나는 새 질문을하고있다.C++에서 std :: function signature에 오버로드하는 방법

나는 + = 연산자를 오버로드하는 클래스가 있습니다. 나는 1 과부하가 노출 된 함수 포인터를 먹고 싶어하고, 다른 하나는 표준 : 기능을 위해 :

void operator+=(void (*handler)()); 
void operator+=(function<void (void *, T)> handler); 

사용법 : 컴파일러가 결정할 수 없기 때문에

MyClass a; 
a += [](){ DoSomething(); }; 
a += [](void *x, T y){ DoSomething(); }; 

불행하게도, 코드가 컴파일되지 않습니다 두 번째 오버로드는 처음 + = 호출에 적합하지 않습니다.

내 연산자 + = 멤버 함수를 정의하여이 문제를 어떻게 해결합니까? 연산자를 사용하는 방법을 변경하고 싶지 않습니다 (예 : 명시 적 캐스트 사용). 나는 그들이 위에서 보여준대로 일하기를 바랍니다.

void operator+=(function<void()> handler); 

을 그러나 다시, 나는 기능 <> 템플릿의 서명을 기반으로 과부하 수 없습니다

또한,뿐만 아니라 다음과 같은 과부하를 준비해야 될 것이다.

자세한 예제는이 스레드를 참조하십시오 : Isn't the template argument (the signature) of std::function part of its type? (나는 스레드에서 언급 된 다양한 솔루션을 구현했는데, 그 중 것도를 컴파일하지 않을 것이다) 나는의 번호에 여러 해 동안 봤는데 프로그래밍

언어,하지만 내 C + + 기술은 약간 녹슬고있다.

+0

** 큰 질문은 : __what 주어진 함수 포인터 또는'std :: function' 오브젝트를 오버로드 연산자'='?에서 수행하려고합니까? __ – zaufi

+0

@zaufi : 어떻게 볼 수 없습니까? 그건 맞지만 괜찮아. 나는 이것을 이벤트 핸들러 함수의 std :: vector에 추가 할 것이다. 나는 기본적으로 C++에서 .NET 이벤트를 구현하고있다. 왜냐하면 그 힘은 이벤트와 속성이 - 마치 클로저와 같이 - 현대 프로그래밍 언어에 절대적으로 필수적인 기능이라는 사실을 머리로 감싸지 않았기 때문입니다. –

+0

그렇다면,'std :: vector'를 exchly 하나 ('void()'제안) 서명으로'std :: function'으로 인스턴스화해야합니다 ... 맞습니까? – zaufi

답변

3

4.7.2 ++ g과 잘 코드를 작품에 따라 :

#include <functional> 
#include <iostream> 

template <typename T> 
typename std::enable_if<std::is_convertible<T, void(*)()>::value>::type 
foo(T&&) 
{ 
    std::cout << "foo(void(*)())" << std::endl; 
} 

void foo(std::function<void(void*,int)>) 
{ 
    std::cout << "foo(std::function<void(void*,int)>)" << std::endl; 
} 

int main() 
{ 
    foo([]{}); 
    foo([](void*,int){}); 
} 

문제는 template <class F> function(F);로 선언 std::function의 생성자에 의해 발생합니다. 그 생성자는 모든 것을 인수로 받아들입니다. 이 인수에 적절한 operator()이 없으면 생성자의 인스턴스화 중에 오류가 생성됩니다.

불행하게도 과부하 해결 프로세스에서는 템플릿 함수를 인스턴스화 할 필요가 없으므로 컴파일러는 모든 것을 std::function 유형으로 변환 할 수 있다고 생각합니다.

+0

고마워, 난 그걸 문제없이 내 수업에 들려 주었다. T를 함수 <>로 캐스팅하려고했을 때 상황이 좀 털이 나더라도. 먼저 그것을 무효화 (*)()해야합니다. 건배. –

+0

필자가 겪어 온 주요한 문제점은 enable_if에 대해 들어 본 적이없고 이해하지 못한다는 것입니다. 나는 그것이 (비슷한 질문에 대한 답을 보는 것에서) 도움이 될 수 있음을 모호하게 알고 있었지만 어떻게 사용되었는지는 몰랐다. 나는 그것이 어떻게 작동하는지 아직도 확신하지 못한다. –

+0

'enable_if'에 대한 정보는 [here] (http://www.boost.org/doc/libs/1_52_0/libs/utility/enable_if.html)와 [here] (http : //en.cppreference .com/w/cpp/types/enable_if). – hpsMouse

0

너는 std::vector<std::function<void()>>이 있으면 너는 과부하의 낱단이있을 필요가없는조차. 가장 간단한 방법은 템플릿 화 된 operator+=을 정의하고, 호출 가능한 객체 또는 함수 포인터에 대해서만 std::enable_if으로 "보호"를 설정하는 것입니다. 따라서 lambda 나 raw 포인터를 전달하면 assign (push_back/emplace_back)에서 자동으로 변환됩니다. std::function을 전달하면 예상대로 할당됩니다.

+0

요점을 놓치고 있습니다. "[]() {}"람다와 "[] (void *, T) {}"람다를 벡터에 추가하고 싶습니다. 공통 컨테이너 클래스에서이를 래핑하고이를 내 벡터에 추가합니다. 다른 람다 서명이 필요 없다는 것을 나에게 믿으려고하면 시간과 광산의 쓸데없는 낭비입니다. –

관련 문제