2012-06-12 2 views
8

C++ 11 람다를 사용하여 응용 프로그램을 개발하기 시작했으며 일부 유형을 함수 포인터로 변환해야합니다. 내가 람다 내에서 함수 또는 메소드 지역 변수를 사용해야하는 경우에함수 포인터에 대한 C++ 11 람다

void (* test)() = []() 
{ 
    puts("Test!"); 
}; 

test(); 

내 문제는 다음과 같습니다 : 이것은 GCC 4.6.0에서 완벽하게 작동

const char * text = "test!"; 

void (* test)() = [&]() 
{ 
    puts(text); 
}; 

test(); 

G ++ 4.6.0 캐스트 오류 코드를 제공합니다 :

main.cpp: In function 'void init(int)': 
main.cpp:10:2: error: cannot convert 'main(int argc, char ** argv)::<lambda()>' to 'void (*)()' in initialization 

사용 자동, 그것은 확인을 작동하는 경우 :

const char * text = "Test!"; 

auto test = [&]() 
{ 
    puts(text); 
}; 

test(); 

내 질문은 : [&]으로 람다 유형을 어떻게 만들 수 있습니까? 내 경우에는 STL std :: function (내 프로그램은 C++ RTTI 및 EXCEPTIONS 런타임을 사용하지 않기 때문에)을 사용할 수없고이 문제를 해결하기위한 간단한 구현 기능이 있습니까?

+8

[XY 문제]의 인스턴스와 유사합니다 (http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). –

+3

캡쳐 람다를 함수 포인터로 변환 할 수 없습니다. 당신이하려고하는 것을 설명하십시오. –

+0

실제 문제가 무엇인지 설명하지는 않았지만 시도한 솔루션을 잘못 설명했습니다. 실제 문제가 무엇인지 알려주세요. – thecoshman

답변

8

내 프로그램이 C++을 사용하지 않기 때문에 STL std :: function을 사용할 수 없습니다. RTTI 및 EXCEPTIONS 런타임)

다음은 std::function과 동일한 내용을 작성해야 할 수 있습니다.

std::function에 대한 유형 삭제의 일반적인 구현에는 대부분의 기능에 대해 RTTI가 필요하지 않습니다. 그것은 일반적인 가상 함수 호출을 통해 작동합니다. 자신의 버전을 쓰는 것이 가능합니다.

는 사실, RTTI가 필요하다는 std::function에있는 유일한 일이 세계에서 가장 유용한 기능하지 않는 target_typetarget 기능입니다. 사용중인 구현에 일반적인 비즈니스를 위해 RTTI가 필요 없다고 가정하면이 함수를 호출하지 않고 std::function을 사용할 수 있습니다.

일반적으로 예외 처리를 사용하지 않도록 설정하면 throw 문을 만날 때 프로그램이 종료되고 오류가 발생합니다.std::function이 방출하는 대부분의 예외는 복구 할 수있는 종류가 아니기 때문에 (function 빈을 호출하고 메모리가 부족함 등) std::function을 그대로 사용할 수 있습니다.

8

캡처가없는 람다 만 함수 포인터로 변환 할 수 있습니다. 이것은이 특별한 경우에 대한 람다의 확장입니다 [*]. 일반적으로 람다는 함수 객체이므로 함수 객체를 함수로 변환 할 수 없습니다.

상태 (캡처)가있는 람다 대신 일반 함수 포인터가 아닌 std::function을 사용하는 것이 좋습니다.


[*] 상태를 유지 람다가 포인터 역할을 전환 할 수 있으면, 어디에 상태가 유지 될 것인가? (이 특정 람다의 인스턴스가 여러 개있을 수 있으며, 각각 별도의 상태를 유지해야하는 자신의 상태가 있음)

+0

글쎄, 만약 당신이 이것을'const int c; –

+0

@BarnabasSzabolcs : 이것에 의존한다. std :: function f (int x) {const int (int i) -> int {return i * c;} c = x; return [c] (int i) {return i * c;}};'. 'f'에 의해 반환 된 functor는 그것의 인수에 의존하고 따라서 상태를가집니다. 캡처가 상수 표현 인 경우에만 일반 함수로 포함될 수 있습니다. –

+0

흠. 나는 부분적으로 동의한다. 여전히 풀 수는 있지만 함수 코드에서 c의 값을 변경하면서 매번 람다 함수의 코드를 복사해야하므로 솔루션이 비쌀 수 있습니다. (또는 함수의 전체 코드를 복사하지 않으면 점프가 느려질 수있는 계획 점프를해야합니다.) –

6

아무 것도 포착하지 않은 람다 만이 함수 포인터로 변환 될 수 있습니다.

std :: function과 같은 것을 사용하거나 쓰지 않으려면 다른 방법으로 캡처 할 항목을 매개 변수로 전달해야합니다. 심지어 구조체를 만들 수 있습니다.

#include <iostream> 

struct captures { int x; }; 
int (*func)(captures *c) = [](captures *c){ return c->x; }; 

int main() { 
    captures c = {10}; 

    std::cout << func(&c) << '\n'; 
} 

또 다른 대안은 캡처가 필요없는 global/static/thread_local/constexpr 변수를 사용하는 것입니다.

관련 문제