C ++ 11에서 std :: function이 비어 있는지 제대로 확인하는 방법은 무엇입니까?


96

std::function비어 있는지 제대로 확인하는 방법이 궁금합니다 . 이 예를 고려하십시오.

class Test {
    std::function<void(int a)> eventFunc;

    void registerEvent(std::function<void(int a)> e) {
        eventFunc = e;
    }

    void doSomething() {
        ...
        eventFunc(42);
    }
};

이 코드는 MSVC에서 잘 컴파일되지만 코드 doSomething()를 초기화하지 않고 호출하면 eventFunc분명히 충돌합니다. 그것은 예상되었지만의 가치가 무엇인지 궁금합니다 eventFunc. 디버거는 말한다 'empty'. 그래서 간단한 if 문을 사용하여 수정했습니다.

   void doSomething() {
        ...
        if (eventFunc) {
            eventFunc(42);
        }
   }

이것은 작동하지만 여전히 초기화되지 않은 값이 무엇인지 궁금합니다 std::function. 나는 쓰고 if (eventFunc != nullptr)싶지만 std::function(분명히) 포인터가 아닙니다.

작동하는 경우 왜 순수합니까? 그 뒤에 숨겨진 마법은 무엇입니까? 그리고, 그것을 확인하는 올바른 방법입니까?


8
참고 eventFunc람다 아니다; 그것은 std::function. std::functions에 람다를 저장할 수 있지만 동일한 것은 아닙니다.
— templatetypedef

3
당신 말이 맞습니다. 혼란을 피하기 위해 제목을 변경했습니다. 감사.
— NightElfik 2014

답변:


104

빈 람다를 확인하는 것이 아니라에 std::function저장된 호출 가능한 대상이 있는지 여부 입니다. 검사는 잘 정의되고 작동하므로 부울 값이 필요한 컨텍스트 (예 : 명령문의 조건식)에서 std::function::operator bool암시 적 변환 bool이 가능합니다 if.

게다가 빈 람다 의 개념은 실제로 의미가 없습니다. 백그라운드에서 컴파일러는 람다 식을 struct(또는 class) 정의 로 변환하고 캡처 한 변수는이 struct. 공용 함수 호출 연산자도 정의되어 있으므로 람다를 호출 할 수 있습니다. 그렇다면 빈 람다는 무엇일까요?


if(eventFunc != nullptr)원하는 경우 작성할 수도 있습니다 . 질문에있는 코드와 동일합니다. 과 비교하기위한 std::function 정의 operator== 및 operator!=오버로드 nullptr_t.


1
하지 않습니다 == nullptr하지만, 같은 일을? 에 과부하가있을 해야하는 것 같습니다 ==에 "빈"원인 운영자 std::function비교할를 true상대로 nullptr: cplusplus.com/reference/functional/function/operators
— 카일 해변

3
@KyleStrand 예에 비교 nullptr도 작동합니다, if(eventFunc != nullptr)동일합니다 if(eventFunc)위의 질문이다.
— Praetorian

3
기술적으로 std::function::operator bool는 암시 적 변환을 bool. 결국 표시 explicit되지만 표준은 부울 표현식을 기대하는 특정 언어 구조에 대해 예외를 만들어 "문맥 적으로 bool로 변환"이라고합니다. 표준의 관련 스 니펫과 설명은 여기에서 찾을 수 있습니다. chris-sharpe.blogspot.com/2013/07/…
— bcrist

@bcrist 네, 부울 변환 연산자가라는 것을 알고 있습니다. explicit그래서 부울 값이 필요한 컨텍스트에서 암시 적 변환을 허용bool 하도록주의를 기울였습니다 . 이것은 문제의 코드에서 정확히 일어나는 일입니다.
— Praetorian

5
@Praetorian 내가 말하고자하는 요점은 표준이 "암시 적 변환"이라는 문구에 매우 구체적인 의미를 할당하고, 또한 매우 특정한 의미를 갖는 "불로의 문맥 변환"과는 확연히 다르다는 것입니다. 여기에는 "Is-a"관계가 없습니다. 나는 초보자가 암묵적 / 명시 적 / 문맥 적 변환의 차이를 즉시 알 필요가 없을 수도 있지만 나중에 오래된 습관을 깨는 것보다 무의식적으로 올바른 단어를 배우는 것이 낫다는 것을 이해합니다.
— bcrist 2015-06-20

21

여기에서 확인하십시오. http://www.cplusplus.com/reference/functional/function/operator_bool/

예

// function::operator bool example
#include <iostream>     // std::cout
#include <functional>   // std::function, std::plus

int main () {
  std::function<int(int,int)> foo,bar;
  foo = std::plus<int>();

  foo.swap(bar);

  std::cout << "foo is " << (foo ? "callable" : "not callable") << ".\n";
  std::cout << "bar is " << (bar ? "callable" : "not callable") << ".\n";

  return 0;
}

산출

foo는 호출 할 수 없습니다.

바는 호출 가능합니다.


31
이 대답은 swap(). 나는 그것을 깨달을 때까지 출력이 거꾸로 생각하고 있었다.
— cp.engr

-1

(명확한 답변을 드리겠습니다.)

a std::function가 비어 있는지 확인할 수 있습니다 std::function::operator bool.

true : 객체가 호출 가능한 경우.
false : 그렇지 않으면 (객체가 빈 함수 임)

예

#include <iostream>
#include <functional>

int main ()
{
    std::function<int(int,int)> foo = std::plus<int>();//assigned: not empty
    std::function<int(int,int)> bar;//not assigned: empty

    std::cout << "foo is " << (foo ? "not empty" : "empty") << ".\n";
    std::cout << "bar is " << (bar ? "not empty" : "empty") << ".\n";

    return 0;
}

산출

foo는 비어 있지 않습니다.
바가 비어 있습니다.


2
결과 문자열이 바뀝니다.
— Sophit

@Sophit 확실합니까? ;)
— zwcloud '1911

1
귀하의 의견은 foo가 비어 있지 않으며 출력에 동의하지 않는다고 말합니다. 귀하의 의견에 동의합니다.
— Sophit
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.