如何正确检查std :: function在C ++ 11中是否为空?


95

我想知道如何正确检查an 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不是lambda。这是一个std::function。您可以将Lambda存储在std::functions中,但它们不是一回事。
templatetypedef

3
您说得对,我更改了标题以避免混淆。谢谢。
NightElfik

Answers:


104

您不是要检查空的lambda,而是要检查其中是否std::function存储了可调用目标。该检查定义明确且有效,因为std::function::operator bool它允许bool在需要布尔值(例如if语句中的条件表达式)的上下文中进行隐式转换。

此外,空lambda的概念实际上没有任何意义。在后台,编译器将lambda表达式转换为struct(或class)定义,并将捕获的变量存储为this的数据成员struct。还定义了一个公共函数调用运算符,它使您可以调用lambda。那么空的lambda是什么呢?


您也可以if(eventFunc != nullptr)根据需要编写代码,它等同于问题中的代码。std::function 定义 operator==operator!=重载以与进行比较nullptr_t


1
但是,不是== nullptr做同样的事情吗?它看起来像有应该是对超载==运营导致的“空” std::function比较true反对nullptrcplusplus.com/reference/functional/function/operators
凯尔东街

3
@KyleStrand是的,与之相比也nullptr将起作用,if(eventFunc != nullptr)相当于if(eventFunc)上面的问题。
Praetorian

3
从技术上讲,std::function::operator bool不允许隐式转换为boolexplicit毕竟,它已被标记,但是该标准对某些期望布尔表达式的语言构造作了例外,称其为“上下文转换为布尔值”。您可以在此处找到相关的标准语段和说明:chris-sharpe.blogspot.com/2013/07/…– bcrist 2015
6

@bcrist是的,我知道布尔转换运算符是explicit,这就是为什么我要谨慎地声明允许bool在需要布尔值的上下文中进行隐式转换的原因。这正是所讨论的代码中正在发生的事情。
Praetorian

5
@Praetorian我要说明的一点是,该标准为短语“隐式转换”赋予了非常具体的含义,它与“上下文转换为bool”有明显的不同,后者也具有非常具体的含义。这里没有“是”关系。我了解,初学者可能不需要立即了解隐式/显式/上下文转换之间的区别,但是与以后不得不改掉旧习惯相比,下意识地学习正确的单词更好。
bcrist 2015年

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
您的结果字符串被交换。
苏菲特

@苏菲特你确定吗?;)
zwcloud

1
您的评论说foo不为空,并且输出不同意。我同意你的评论。
苏菲特
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.