지역 - c++ 함수 포인터



람다 식을 람다 인수로 전달 c++ 11 (4)

std :: function을 사용해보십시오 :

#include <functional>
int main()
{
    int x=0;
    int y=0;
    auto f = [x,y](std::function<double(int)> func) -> double
             {func(0); return 0.0;};

    f([x](int i) -> double {return 0.0;});
}

https://ffff65535.com

나는 이런 식으로하고 싶다 :

int main()
{
    auto f = [/*some variables*/](/*take lambda function*/)
    {/*something with lambda function*/};

    f([/*other variables*/](/*variables to be decided by f()*/)
    {/*something with variables*/});
}

나는 람다뿐만 아니라 함수에 람다를 전달하는 것이 가능하다는 것을 안다. 다음 작품들 :

int main()
{
    int x=0;
    int y=0;
    auto f = [x,y](double (func)(int)) -> double
    {func(0); return 0.0;};

    f([](int i) -> double
    {return 0.0;});
}

하지만 다음은 작동하지 않습니다 (즉, 범위 변수를 변경하여 [x] 추가).

int main()
{
    int x=0;
    int y=0;
    auto f = [x,y](double (func)(int)) -> double
    {func(0); return 0.0;}

    f([x](int i) -> double    //[x] does not work
    {return 0.0;});
}

오류를 제공합니다 :

error: function "lambda [](double (*)(int))->double::operator()" cannot be called with the given argument list
        argument types are: (lambda [](int)->double)
        object type is: lambda [](double (*)(int))->double

누구든지이 문제를 해결하는 방법이나 그 방법을 알고 싶습니까? 나는 intel 컴파일러 icpc (ICC) 13.1.2 std = c ++ 11을 사용하고 있습니다.

감사


귀하의 질문에 대해 명확히 할 몇 가지 사항이 있습니다. 첫 번째 는 람다 (lambda) 무엇입니까?

람다 식은 컴파일러가 이름을 지정할 수없는 고유 한 유형을 생성하고 동시에 유형의 인스턴스를 생성하는 간단한 표현식입니다. 당신이 쓸 때 : [](int i) { std::cout << i; } [](int i) { std::cout << i; } 컴파일러는 대략 다음과 같은 형식을 생성합니다.

struct __lambda_unique_name {
   void operator()(int i) const { std::cout << i; }
};

보시다시피, 함수는 아니지만 operator()const 멤버 함수로 구현하는 유형입니다. 람다가 임의의 캡처를 수행하면 컴파일러는 값 / 참조를 캡처하는 코드를 생성합니다.

위와 같은 람다의 경우, 상태가 캡처되지 않는 곳에서 언어는 람다 형식에서 operator() 의 서명 ( this 부분 제외 operator() 으로의 포인터로의 변환을 허용하므로 위의 람다는 암묵적으로 int 취하고 아무것도 리턴하지 않는 함수로의 포인터로 변환 될 수있다.

void (*f)(int) = [](int i) { std::cout << i; }

기본 사항이 명시되었으므로 코드에는 다음과 같은 람다가 있습니다.

auto f = [x,y](double (func)(int)) -> double {func(0); return 0.0;};

함수에 대한 매개 변수 (람다에도 적용되는)에 대한 규칙은 인수가 함수 유형이 될 수 없다는 것을 결정하므로 람다에 대한 인수는 함수 에 대한 포인터로 쇠퇴합니다 (array 유형의 인수가 포인터로 쇠퇴하는 것과 같은 방식으로). 유형):

auto f = [x,y](double (*func)(int)) -> double {func(0); return 0.0;};

나중에는 인수를 인수로 갖는 람다를 전달하려고합니다. 캡쳐가 있기 때문에 특별 규칙이 적용되지 않으며 람다가 컴파일러 오류를 생성하는 함수 포인터로 변환 될 수 없습니다.

현재 표준에서는 두 가지 방법 중 하나를 선택할 수 있습니다. 유형 지우기를 사용하여 서명에서 호출 가능 엔티티의 정확한 유형을 제거 할 수 있습니다.

auto f = [x,y](std::function<double(int)> func) -> double {func(0); return 0.0;};

std::function<double(int)> 은 적절한 서명이있는 호출 가능 엔터티로 초기화 될 수 있으므로 아래 코드에서 일반적으로 동적 할당과 동적 디스패치를 ​​의미하는 유형 삭제 비용을 수반하여 람다를 허용합니다 .

또는 구문 설탕을 버리고 첫 번째 람다 등가 물을 수동으로 굴릴 수는 있지만 일반적으로 만듭니다. 이 경우 람다가 단순한 곳은 유효한 옵션 일 수 있습니다 :

struct mylambda {
   template <typename F>
   double operator()(F fn) const {
      fn(0); return 0.0;
   }
} f;
// then use the non-lambda as you tried:
f([x](int i) -> double {return 0.0;});

마지막으로, 충분히 참을성이 있다면, C ++ 14를 기다릴 수 있습니다. (아마도 비준되지 않았습니다) 위 클래스의 생성을 단순화하는 다형성 람다 (polymorphic lambdas)에 대한 지원이있을 것입니다.

auto f = [](auto fn) { fn(0.0); return 0.0; } // unrolls to 'mylambda' above

암흑 시대에했던 것처럼 총알을 간단히 물고 자신의 펑터를 구현해야 할 수도 있습니다.

struct F {
    int x;
    int y;

    F(int x_, int y_) : x(x_), y(y_) {}

    template <typename G>
    double operator() (G&& g) const {
        g(0);
        return 0.0;
    }
};

#include <iostream>

int main()
{
    int x = 0;
    int y = 0;
    auto f = F(x, y);

    f([x](int i){return 0.0;});
    f([](int i){std::cout << i << std::endl;});
}

컴파일러가 C ++ 14 일반 람다를 지원할 때까지 계속 그렇게해야합니다.


캡쳐 람다를 cify 할 수 있지만이 솔루션에는 한계가 있습니다.

#include <new>

#include <utility>

namespace
{

template <typename F, int I, typename L, typename R, typename ...A>
inline F cify(L&& l, R (*)(A...) noexcept(noexcept(
  std::declval<F>()(std::declval<A>()...))))
{
  static L l_(std::forward<L>(l));
  static bool full;

  if (full)
  {
    l_.~L();

    new (static_cast<void*>(&l_)) L(std::forward<L>(l));
  }
  else
  {
    full = true;
  }

  return [](A... args) noexcept(noexcept(
      std::declval<F>()(std::forward<A>(args)...))) -> R
    {
      return l_(std::forward<A>(args)...);
    };
}

}

template <typename F, int I = 0, typename L>
inline F cify(L&& l)
{
  return cify<F, I>(std::forward<L>(l), F());
}


int main()
{
    int x=0;
    int y=0;
    auto f = [x,y](double (func)(int)) -> double
    {func(0); return 0.0;};

    f(cify<double(*)(int i)>([x](int i) -> double    //works now
    {return 0.0;}));
}

실제 사례를 Click .





icc