2011-11-03 2 views
5

람다를 사용하여 복잡성을 크게 줄일 수있는 몇 가지 코드가 있습니다. 그러나 불행하게도 우리는 C++ 11을 완전히 지원하지 않는 컴파일러를 사용해야하며 쉽게 전환 할 수 없습니다. 이제 문제는 논리를 가능한 한 가깝게 람다 식으로 유지하는 방법입니다 (예 : std::function은 사용할 수 있지만 람다는 사용할 수 없음).사전 람다 컴파일러에서 람다를 처리하는 방법

일반적인 해결책은 다른 곳에 펑터를 정의하고 적절한 장소에서 그것을 사용하는 것입니다 : 나는 정말이 패턴에 익숙해

struct functor{ 
    functor(type & member) : m_member(member) {} 
    void operator()(...) {...} 
    type & m_member; 
}; 

void function() { 
    use_functor(functor(...)); 
} 

, 내가 많이 싫어하지만. 클래스를 정의하지 않는 주된 이유는 보통 함수가 STL 내에서 사용되며 템플릿은 함수의 인라인으로 정의 된 구조체를 좋아하지 않는다는 것입니다. 그러나 내 경우에는 use_functor() 함수가 정상적인 방법이 될 것이므로 함수 내부에 함수를 정의 할 수 있습니다 (각 함수는 한 함수 내에서만 사용됩니다).

void function() { 
    struct functor{ 
     functor(type & member) : m_member(member) {} 
     void operator()(...) {...} 
     type & m_member; 
    }; 
    use_functor(functor(...)); 
} 

다소 개선되었지만 여전히 좋지 않은 코드가 필요합니다. 예를 들어 나는 펑서의 이름을 모두 없애고 싶습니다. 하나의 값만 사용하는 경우 익명 구조체를 만드는 것이 가능하다는 것을 알고 있습니다.

void function() { 
    struct{ 
     // functor(type member) : m_member(member) {} 
     void operator()(...) {...} 
     // type & m_member; 
    } callback ; 
    use_functor(callback); 
} 

그러나이 시점에서 필요한 데이터 멤버를 제공하는 방법에 대한 단서가 없습니다. 구조체는 익명이므로 생성자가 없습니다. 나는 그것이 public이기 때문에 쉽게 멤버를 설정할 수있다. 그러나 다시 이것은 내가 싫어하는 라인을 추가 할 것이다.

목표는이 문제를 완전히 제거 할 수있는 깨끗한 람다를 가진 컴파일러로 전환 한 후에 가능한 한 적은 변경이 필요한 상태로 두는 것입니다.

어떻게하면 되나요? 생성자없이 익명 struct의 멤버 변수의 initalisation 관련하여

+0

일부 구형 GCC는 std :: function <>으로 중첩 된 구조체의 변환을 처리하지도 않으며 솔루션을 좋아하지 않을 것입니다. 그래서 옵션 1을 사용하고 로직을 분리해야합니다. – LiKao

답변

1

당신은 할 수 있습니다 :

void function() { 
    type the_thing; 
    struct { 
     void operator()(...) {...} 
     type & m_member; 
    } callback = {the_thing}; 
    use_functor(callback); 
} 

callbacktype & 참조 m_member을 설정할 수 있습니다.

0

awoodland에 의해 대답에 확장 :

#define MY_LAMBDA(name, memberType, memberValue, body) \ 
    struct {          \ 
     void operator()(...) body    \ 
     memberType & memberValue;     \ 
    } name = {memberValue} 

void function() { 
    type thing_to_capture; 

    MY_LAMBDA(callback, type, thing_to_capture 
    { 
     std::cout << thing_to_capture << std::endl; 
    }); 

    use_functor(callback); 
} 

을 당신은 어디에서든지 당신이 구조체를 정의 할 수 있습니다 MY_LAMBDA를 사용할 수 있습니다. 불행히도 variadic 매크로가 없으면 캡처 된 모든 객체를 단일 객체로 래핑하고 "람다 선언"에서 해당 객체의 유형을 지정해야합니다.

또한 람다를 사용하는 동등 물은

입니다.
void function() { 
    type thing_to_capture; 

    auto callback = [&thing_to_capture]() 
    { 
     std::cout << thing_to_capture << std::endl; 
    }; 

    use_functor(callback); 
} 
+0

오타가 발생할 가능성을 없애기 위해 매크로의 맨 위에'type thing_to_capture;를 추가 할 수 있습니다 (이 예에서와 같이 명시 적 c'tor도 복사 할당도 호출하지 않는 경우). – Richard

+1

'MY_LAMBDA'는'operator()'의 정의를 지정하지 않으면 어떻게 유용합니까? – ildjarn

+0

@ildjarn 좋은 지적 ... 편집 중입니다. –

0

부스트 람다 라이브러리 또는 boost::phoenix을 사용해보세요. 그들은 둘 다 실제 람다 지원없이 람다 스타일 작업을 수행하도록 설계되었습니다. 템플리트 기반이기 때문에 예상대로 작동하지 않을 때 오류를 디버그하기가 어려울 수 있습니다.

관련 문제