VS2012 std::function operator bool неочаквано връща true

Попаднах на странно поведение във VS2012 със std::function, за което не можах да намеря нищо онлайн.

Дадена е следната примерна програма:

#include <functional>
#include <iostream>

typedef std::function< int()> fntype;

void foo(const fntype& fn)
{
    try
    {
        if(fn)
            fn();
        else
            std::cout << "fn is empty" << std::endl;
    }
    catch(const std::bad_function_call&)
    {
        std::cout << "fn threw anyways" << std::endl;
    }
}


int main(int argc, char **argv)
{
    // OK
    std::function<int()> nothing;
    foo(nothing);

    // Fails
    std::function<const int()> nothing2;
    foo(nothing2);
    
    return 0;
}

Второто извикване на foo() се компилира (въпреки че const на връщания тип не съответства на fntype. Въпреки това, if(fn) се оценява на true въпреки това.

Резултатът е:

fn е празен

fn все пак хвърли

Забележка: В програмата за отстраняване на грешки fn се показва като празен и в двата случая

Това поведение не може да бъде възпроизведено с GCC (Coliru). Тук се получава очакваният резултат:

Резултатът е:

fn е празен

fn е празен

Това проблем ли е в изпълнението на VS2012 на стандартната библиотека?

Има ли начин за заобикаляне на проблема чрез: a) Оценката на fntype::operator bool() на false в случай 2 или b) Неуспешна компилация поради несъответствие на подписа.


person namezero    schedule 09.03.2015    source източник


Отговори (1)


Изглежда, че това е грешка от 2012 г., изглежда не се случва през 2013 г. вижте го на живо това списък с грешки: 44 грешки в C++11 също са коригирани във Visual Studio 2013 споменава, че това е коригирано през 2013 г. и се казва:

В някои случаи преобразуването може да доведе до неправилен резултат във VS2012 поради това, че функционалният обект не е празен, когато трябва да бъде. Например:

// JetPlane derives from Plane
function<bool(JetPlane*)> plane_ready_func = function<bool(Plane*)>();
if (plane_ready_func)   // should yield false but doesn't
{
    plane_ready_func(nullptr);   // gets called and throws bad_function_call
}

Конструкторът по подразбиране за std::function трябва да създаде празна функция.

Намерих поне един един доклад за грешка, който е в съответствие със списъка с грешки по-горе.

person Shafik Yaghmour    schedule 09.03.2015
comment
Благодаря за потвърждението. Бях попадал на тази страница и преди, но не бях свързвал този пример с разглеждания проблем. Ще приема това като решение, тъй като потвърждава подозрението ми. - person namezero; 10.03.2015