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.