2014-12-19 1 views
0

좋아,이 간단해야, 기본적으로 아래의 예는 (적어도 컴파일) 을 일해야 : 클로저를«클래스 메서드 포인터»로 제공 하시겠습니까?

class Foo { 
public: 
    void DoNothing(void(Foo::*funcptr)()){} 
    void CallDoNothing(); 
}; 

void Foo::CallDoNothing(){ 
    auto closure = [this](){}; 
    DoNothing(closure); 
} 

int main(){ 
    return 0; 
} 

그러나

컴파일 오류를

test.cpp: In member function ‘void Foo::CallDoNothing()’: 
test.cpp:9:19: error: no matching function for call to ‘Foo::DoNothing(Foo::CallDoNothing()::__lambda0&)’ 
    DoNothing(closure); 
       ^
test.cpp:9:19: note: candidate is: 
test.cpp:3:7: note: void Foo::DoNothing(void (Foo::*)()) 
    void DoNothing(void(Foo::*funcptr)()){} 
    ^
test.cpp:3:7: note: no known conversion for argument 1 from ‘Foo::CallDoNothing()::__lambda0’ to ‘void (Foo::*)()’ 

내가 트리거 몇 가지 이유 이미 캐스팅을 시도해 보았습니다. DoNothing(reinterpret_cast< void(Foo::*funcptr)() >(closure));, DoNothing((void(Foo::*funcptr)())closure);에 약간의 변형이 추가되었습니다.이 모든 것이 컴파일 오류를 유발했습니다.

+1

캡쳐 된 람다는 멤버 함수 포인터는 물론 함수 포인터로 변환 될 수 없습니다. – user657267

+0

@ user657267 글쎄, 이것이 정말로 슬픈 일이라면, 이것은 매우 슬픈 일이다. 그렇다면 클로저 (즉, 로컬 변수가 포착 된 람다)를 받아들이는 인수를 어떻게 선언 할 수 있습니까? –

+1

'std :: function ' – user657267

답변

2

람다 함수를 멤버 함수 포인터에 할당 할 수 있다고 생각하는 이유는 무엇입니까? 람다 함수는 익명의 타입입니다. 비어있는 캡처가있는 경우에만 함수 포인터에 할당 할 수 있지만 그 경우에도 함수 포인터와 호환되지 않습니다.

std::function<void()>을 사용하거나 DoNothing을 템플릿 기능으로 만들 수 있습니다.

+0

클로저가없는 람다가 컴파일러에 의해 간단한 함수 포인터로 암시 적으로 형 변환 될 수 있기 때문에 그렇게 생각하고 있습니다. 다음으로 우리는 스스로에게 묻습니다.이 단순한 람다와 폐쇄의 차이점은 무엇입니까? 다음으로 우리는 클래스 함수 포인터가 이들을 첫 번째 인수로 암시 적으로 받아들이 기 때문에 일반적인 함수 포인터와 다르다는 것을 기억합니다. 그래서 분명히 클로저는«클래스 메소드 포인터»에만 캐스트 될 수 있습니다. ≈ –

+1

@ Hi-Angel 빈 캡쳐가있는 람다 함수 만 함수 포인터에 할당 될 수 있고 언어가 캡쳐 된 람다에 대해 아무 것도 정의하지 않는다는 것을 알고 있다면, 나는 그곳에 있다고 가정하는 것을 용감하게 느낍니다. 이것을 캡쳐 한 람다와 멤버 함수 포인터 사이의 관계이다. 의미 론적 수준에서는 합리적이라고 생각되지만 컴파일러는 언어 정의를 따라야합니다. 이것이 말하지 않기 때문에, 나는 당신이 왜 그것이 작동한다고 가정해야하는지 알지 못합니다. 논리 인수와 언어 표준은 때때로 매우 다릅니다 :-) – Jens

+0

음, tbh 언어 표준이 클로저에 대한 캐스트를 정의하지 않는다는 것을 알지 못했기 때문에 실제 프로그램에 혀짤임 함수를 작성하려고했습니다 그리고 마지막으로이 질문을 던졌다. –