Error on implicit cast from std:unique_ptr to bool
Asked Answered
T

2

10

I am using Allegro to create a simple game. When I try to validate that my pointer to the display is not null I get a compiler error telling me

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

Here is my code

#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;
}

If I pass validate "!display" instead of "display" it works. I realize I could call validate with display.get(), but I wanted to know why it isn't working when I pass a smart pointer.

I found this bug report. I am using Visual Studio 2013. https://connect.microsoft.com/VisualStudio/feedbackdetail/view/775810/c-11-std-unique-ptr-cast-to-bool-fails-with-deleter-lambda

Therein answered 29/5, 2015 at 5:36 Comment(0)
F
20

std::unique_ptr is not implicitly convertible to bool. It is contextually convertible to bool (due to its explicit conversion operator), which is why you can use it in an if statement, or put a ! in front of it, but you cannot pass it as an argument to a function which is expecting a bool.

Fontana answered 29/5, 2015 at 5:46 Comment(0)
E
1

The best idea is to use a macro for such validation. There are couple of reasons:

1) because you can (and you should) remove validation code when you build without _DEBUG (release build), so:

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

thanks to such approach you have the same code that is using validations but when you build Release you have no performance loss because of using validations (usually when you get an assert in debug you also get same assert in release build)

2) you can use what I've used in code sample above:

!!(test)

which forces bool cast. Now you can write:

std::unique_ptr ptr{...};
VALIDATE(ptr, "FAIL: Wrong ptr!");
Etzel answered 23/4, 2016 at 8:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.