명시 적으로 반환 유형을 명시하더라도 람다에 대한 호출은 모호합니다.


11

람다의 유형을 결정할 수있는 경우 오버로드 된 함수는 두 함수를 모두 가져 와야합니다 std::function((잘못된 경우 수정하십시오). 질문은 다음과 같습니다. 정의 되었습니까? ( [&]() -> Type {})

현재 솔루션의 경우 참조 기준 캡처가 필요하므로 코드에 논리가 포함되어 있습니다.

다음 예제는 문제점을 설명합니다.

#include <iostream>
#include <string>    
#include <functional>

void do_some(std::function<void(int)> thing) 
{
   thing(5);
}

void do_some(std::function<bool(int)> thing)
{
   if (thing(10)) 
   {
      std::cout << "it's true!" << std::endl;
   }
}

int main()
{
   int local_to_be_modified = 0;
   do_some(
      [&](int in)
      {
         local_to_be_modified = in;
         std::cout << "This is void-" << std::endl;
      }
   );
   do_some(
      [&](int in) -> bool
      { 
         // error: call to 'do_some' is ambiguous
         local_to_be_modified += in;
         std::cout << "This is bool-" << std::endl;
         return true;
      }
   );
}

6
std::function<void(int)>무언가를 반환하는 람다에서도 생성 될 수 있기 때문에 반환 값이 무시됩니다.
HolyBlackCat

1
따로, 해당 람다의 리턴 유형을 명시 적으로 지정하면 정확히 아무것도 수행되지 않습니다.
중복 제거기

답변:


8

2 람다 식을 반환하기 때문에 bool모두 변환 할 수 std::function<void(int)>std::function<bool(int)>암시.

std::function 변환 생성자가 있습니다.

template< class F >
function( F f );

이 생성자는 f가 인수 유형 Args ...에 대해 호출 가능 하고 유형 R을 리턴 하지 않는 한 과부하 해결에 참여하지 않습니다 (C ++ 14부터).

의 정의로 호출 가능 ,

다음 표현식이 유효해야합니다.

INVOKE<R>(f, std::declval<ArgTypes>()...)

여기서 INVOKE (f, t1, t2, ..., tN)static_cast<void>(INVOKE(f, t1, t2, ..., tN))R이 cv-qualified void인 것처럼 정의되고 , 그렇지 않으면 INVOKE (f, t1, t2, ..., tN) 은 암시 적으로 R로 변환됩니다

위에 표시된 것처럼에 bool대한을 반환하는 두 번째 람다 는 유효한 표현식입니다 (반환 은로 변환 됨 ). 그러면 암시 적으로 변환되어 모호성 문제가 발생할 수 있습니다 .std::function<void(int)>static_cast<void>(INVOKE(f, t1, t2, ..., tN))boolvoidstd::function<void(int)>


6

static_cast람다를 올바른 유형 으로 명시 적으로 지정할 수 있습니다

using FunBoolRet = std::function<bool(int)>;

do_some(static_cast<FunBoolRet >([&](int in) 
   {
      local_to_be_modified += in;
      std::cout << "This is bool-" << std::endl;
      return true;
   }));

또는 람다를 올바른 std::function<bool(int)>유형으로 저장하고 함수에 전달하십시오 ( do_some(lmda)여러 번 호출 해야하는 경우 )

FunBoolRet lmda = [&](int in)
{
    local_to_be_modified += in;
    std::cout << "This is bool-" << std::endl;
    return true;
};    
do_some(lmda); // pass the lambda

또는 @MaxLanghof가 제안한 것처럼 단순히 std::function<bool(int)>이동 중에 람다에서 생성

do_some(FunBoolRet{
   [&](int in) 
   {
      local_to_be_modified += in;
      std::cout << "This is bool-" << std::endl;
      return true;
   }
});

당신은 건너 뛰고 바로 그것을 직접 static_cast만들 수 있습니다 std::function. 어쨌든 암시 적 변환 중에 일어나는 모든 것입니다.
Max Langhof

내 요점은 말 그대로 static_cast<및 마지막을 제거 >할 수 있으며 동일한 작업을 수행하지만 입력 횟수는 줄어든다는 것입니다. 더 많은 줄이나 다른 것이 필요하지 않습니다. godbolt.org/z/fQTqF4
Max Langhof
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.