Error when implicitly pushing from std: unique_ptr for bool

I am using Allegro to create a simple game. When I try to check that my display pointer 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 the test "! Display" instead of "display" it works. I understand that I can call validate with display.get (), but I wanted to know why it doesn't work when I pass in 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

+3


source to share


2 answers


std::unique_ptr

implicitly converts to bool. It is contextually convertible to bool (because of its explicit conversion operator), so you can use it in an if statement or prepend !

it, but you cannot pass it as an argument to a function expecting a bool.



+9


source


The best idea is to use a macro for this kind of check. There are several reasons:

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

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

      

with this approach, you have the same code that uses validations, but when you build a Release, you have no performance loss due to the use of validations (usually when you get the assert debug, you also get the same assertion in the release build)



2) you can use what I used in the example code above:

!!(test)

      

which makes the bool cast. Now you can write:

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

      

+1


source







All Articles