Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange behavior with std::function

I'm using the standard function wrapper from the C++11 library, and I am seeing some strange behavior with its boolean operator. If I create a std::function object the boolean operator returns false. This is still true if I assign nullptr to the object and check again. The problem appears when I assign it a void pointer which I have cast into a function pointer. Consider the following program:

#include <functional>
#include <iostream>

void* Test() {
    return nullptr;
}

int main(int argc, char* argv[]) {
    std::function<void()> foo;
    std::cout << !!foo << std::endl;

    foo = nullptr;
    std::cout << !!foo << std::endl;

    foo = reinterpret_cast<void(*)()>(Test());
    std::cout << !!foo << std::endl;

    return 0;
}

What I expect as output is 0 0 0 but the result is 0 0 1 (see demo). Can anyone explain why the boolean operator returns true when it contains a null, non-callable function pointer? And please also mention a workaround to check for nullptr in std::function

NOTE: I've already tried checking if the target is null (with foo.target<void*>() == nullptr) instead of using the boolean operator, but it seems as if no matter what the function object contains, the target is always null (even when the function object is perfectly fine with being called).

like image 814
Elliott Darfink Avatar asked Jan 12 '23 02:01

Elliott Darfink


1 Answers

Looks like a bug to me. First, here's a simplified example that doesn't play any games with casts:

#include <functional>
#include <iostream>

typedef void (*VF)();

VF Test() {
    return nullptr;
}

int main(int argc, char* argv[]) {
    std::function<void()> foo(Test());
    std::cout << !!foo << std::endl;
    return 0;
}

It still prints 1 with GCC. It shouldn't:

20.8.11.2.1
template<class F> function(F f);
template <class F, class A> function(allocator_arg_t, const A& a, F f);
7 Requires: F shall be CopyConstructible. f shall be Callable (20.8.11.2) for argument types ArgTypes and return type R. The copy constructor and destructor of A shall not throw exceptions.
8 Postconditions: !*this if any of the following hold:

  • f is a NULL function pointer.
  • f is a NULL pointer to member.
  • F is an instance of the function class template, and !f
like image 152
Igor Tandetnik Avatar answered Jan 22 '23 10:01

Igor Tandetnik