从 std:unique_ptr 到 bool 的隐式转换错误

Error on implicit cast from std:unique_ptr to bool

我正在使用 Allegro 创建一个简单的游戏。当我尝试验证指向显示器的指针不为空时,我收到一个编译器错误,告诉我

error C2664: 'void validate(bool,std::string)' : cannot convert argument 1 from 'std::unique_ptr< ALLEGRO_DISPLAY,main::< lambda_996846ce92067e506da99cad36e610cf>>' to 'bool'

这是我的代码

#include <iostream>
#include <memory>
#include <string>

#include <allegro5\allegro.h>

using namespace std;

const int WIDTH = 512;
const int HEIGHT = 512;

void validate(bool ptr, string errorMessage) {
    if (!ptr) {
        cerr << errorMessage << endl;
        exit(-1);
    }
}

int main() {
    auto deleter = [](ALLEGRO_DISPLAY* d) { al_destroy_display(d); };
    unique_ptr<ALLEGRO_DISPLAY, decltype(deleter)> display;

    validate(al_init(), "Failed to initialize Allegro");
    display = unique_ptr<ALLEGRO_DISPLAY, decltype(deleter)>(al_create_display(WIDTH, HEIGHT), deleter);
    validate(display, "Failed to create display");

    return 0;
}

如果我通过验证“!display”而不是 "display",它会起作用。我意识到我可以使用 display.get() 调用验证,但我想知道为什么当我传递智能指针时它不起作用。

我找到了这个错误报告。我正在使用 Visual Studio 2013。 https://connect.microsoft.com/VisualStudio/feedbackdetail/view/775810/c-11-std-unique-ptr-cast-to-bool-fails-with-deleter-lambda

std::unique_ptr 不能隐式转换为 bool。它可以根据上下文转换为 bool(由于它的 explicit conversion operator),这就是为什么你可以在 if 语句中使用它,或者在它前面放一个 !,但你不能将它作为参数传递到一个期待布尔值的函数。

最好的办法是使用宏进行此类验证。有几个原因:

1) 因为你可以(而且你应该)在没有_DEBUG(发布版本)的情况下构建时删除验证代码,所以:

#if _DEBUG
# define VALIDATE(test, msg) validate(!!(test), msg)
#else
# define VALIDATE(test, msg)
#endif // _DEBUG

感谢这种方法,您拥有使用验证的相同代码,但是当您构建 Release 时,您不会因为使用验证而导致性能损失(通常当您在调试中获得断言时,您也会在发布构建中获得相同的断言)

2) 您可以使用我在上面的代码示例中使用的内容:

!!(test)

强制 bool 转换。现在你可以写:

std::unique_ptr ptr{...};
VALIDATE(ptr, "FAIL: Wrong ptr!");