C ++ 0x : 람다를 참조로 매개 변수로받는 적절한 방법


82

int->int참조 로 람다 매개 변수 를받는 함수를 정의하는 올바른 방법은 무엇입니까 ?

void f(std::function< int(int) >& lambda);

또는

void f(auto& lambda);

마지막 형식이 합법적 인 구문인지 잘 모르겠습니다.

람다 매개 변수를 정의하는 다른 방법이 있습니까?


10
참조로 람다가 필요한 이유는 무엇입니까? 의미 const&합니까?
deft_code 2011-06-23

답변:


83

auto매개 변수를 가질 수 없습니다 . 기본적으로 두 가지 옵션이 있습니다.

옵션 # 1 : std::function표시된대로 사용하십시오 .

옵션 # 2 : 템플릿 매개 변수 사용 :

template<typename F>
void f(F &lambda) { /* ... */}

옵션 # 2는 경우에 따라 포함 된 람다 함수 개체에 대한 잠재적 인 힙 할당을 피할 수 있기 때문에 더 효율적일 수 있지만 f헤더에 템플릿 함수로 배치 할 수있는 경우에만 가능 합니다. 또한 모든 템플릿과 마찬가지로 컴파일 시간과 I- 캐시 공간을 늘릴 수 있습니다. 람다 함수 개체가 충분히 작은 경우 std::function개체 에서 인라인으로 표시 될 수 있으므로 효과가 없을 수도 있습니다 .


1
템플릿은 또한 일반 비 로컬 코드로의 점프를 제거하여 I- 캐시 풋 프린트를 개선 할 수 있습니다 (이 경우 std::function먼저 범용 래퍼를
건너 뛰지

5
"람다 함수 개체가 충분히 작 으면 std::function개체 에서 인라인으로 표시 될 수 있습니다"라는 이 인용문 은 잘못된 것입니다. Lambda는 항상 인라인으로 사용할 수 있습니다 (물론 컴파일러는 선택하지 않을 수 있습니다). std::function구현은 일반적으로 힙 할당을 피하기 위해 작은 개체 최적화를 사용합니다. 람다에 충분히 작은 캡처 목록 이 있으면 std::function힙을 사용하지 않고 저장됩니다 . 그 외에는 람다의 크기는 실제 의미가 없습니다.
deft_code 2011-06-23

2
@bdonlan : 그런데, 왜 거기 &void f(F & lambda)있습니까?
Nawaz

2
@bdonlan :하지만 const &는 람다의 멤버 (값별 캡처)를 변경할 수 없다고 가정합니다. 사용자가 원하는 것이 아닐 수 있습니다.
Nicol Bolas 2011 년

2
@bdonlan 오래되었지만 상수가 아닌 참조로 전달하면 함수 호출에서 임시 람다를 생성 할 수 없습니다. 여기서 r- 값 참조가 가장 좋습니다.
zennehoy

45

다음 template과 같이 사용 합니다.

template<typename Functor>
void f(Functor functor)
{
   cout << functor(10) << endl;
}

int g(int x)
{
    return x * x;
}
int main() 
{
    auto lambda = [] (int x) { cout << x * 50 << endl; return x * 100; };
    f(lambda); //pass lambda
    f(g);      //pass function 
}

산출:

500
1000
100

데모 : http://www.ideone.com/EayVq


13

7 년이 지났다는 것을 알고 있지만 여기에 아무도 언급하지 않은 방법이 있습니다.

void foo(void (*f)(int)){
    std::cout<<"foo"<<std::endl;
    f(1); // calls lambda which takes an int and returns void
}
int main(){
    foo([](int a){std::cout<<"lambda "<<a<<std::endl;});
}

출력되는 내용 :

foo
lambda 1

템플릿이나 std :: function 필요 없음


10
이것은 함수 포인터 (캡처가없는 람다)로 감쇠 할 수있는 람다로만 제한되며, std::function템플릿 버전에는이 제한이없는 동안 정확한 서명 ( 경우 와 동일)을 지정해야합니다 .
Andriy Tylychko

1

void f(auto& lambda);

가까워요. 실제로 컴파일되는 것은 다음과 같습니다.

#include <cassert>

/*constexpr optional*/ const auto f = [](auto &&lambda)
{
  lambda();
  lambda();
};

int main()
{
  int counter = 0;
  f([&]{ ++counter; });
  assert(counter == 2);
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.