6

I am wondering if there is any way to check if a function pointer you assigned into an std::function was a nullptr. I was expecting the !-operator to do it, but it only seems to work when the function has been assigned something of type nullptr_t.

typedef int (* initModuleProc)(int);

initModuleProc pProc = nullptr;
std::function<int (int)> m_pInit;

m_pInit = pProc;
std::cout << !pProc << std::endl;   // True
std::cout << !m_pInit << std::endl; // False, even though it's clearly assigned a nullptr
m_pInit = nullptr;
std::cout << !m_pInit << std::endl; // True

I wrote this helper function to work around this for now.

template<typename T>
void AssignToFunction(std::function<T> &func, T* value)
{
    if (value == nullptr)
    {
        func = nullptr;
    }
    else
    {
        func = value;
    }
}
Deduplicator
  • 44,692
  • 7
  • 66
  • 118
Erik Welander
  • 83
  • 1
  • 7
  • You mean "assigned something of type `nullptr_t`", right? When I first read the answers, I thought you were making a distinction between initialization and assignment, but now I see otherwise. – Ben Voigt Aug 05 '13 at 19:31
  • 2
    Please avoid non-portable crap like `__cdecl` and `HWND` in examples, your question does not rely on anything Windows-specific, so there is no reason not to use a function type such as `void()` that can be tested by anyone on any platform. – Jonathan Wakely Aug 05 '13 at 19:34
  • I removed the Windows-specific parts, and change it to "type nullptr_t" – Erik Welander Aug 05 '13 at 19:50

1 Answers1

8

That's a bug in your std::function implementation (and also apparently in mine), the standard says that operator! shall return true if the object is constructed with a null function pointer, see [func.wrap.func] paragraph 8. The assignment operator should be equivalent to constructing a std::function with the argument and swapping it, so operator! should also return true in that case.

Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
  • Isn't it a `explicit operator bool()`? – dyp Aug 05 '13 at 19:29
  • 1
    @DyP: And `!` causes contextual conversion to bool, which invokes the explicit operator. – Ben Voigt Aug 05 '13 at 19:30
  • @DyP, I was referring to the global `operator!` that's used in the testcase, not `std::function::operator!` (which doesn't exist.) – Jonathan Wakely Aug 05 '13 at 19:31
  • 10
    Apparently someone called Jonathan Wakely reported this as a bug in libstdc++ and said they were going to fix it: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57465 -- Oops. – Jonathan Wakely Aug 05 '13 at 19:57
  • 1
    @Xeo, G++ refuses to deduce a function type for `const T*` because you can't have a const-qualified function, the workaround allows deduction to succeed because it no longer needs to form a const-qualified function type. The correct behaviour isn't clear, see core issues [1584](http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1584) and [503](http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#503) – Jonathan Wakely Aug 05 '13 at 22:49
  • If there are no const-qualified functions, what is `T` in `template void f(T C::*);` and `f(&A::const_function)`? – Xeo Aug 05 '13 at 23:24
  • @Xeo, that's not the same, see [dcl.fct] p6, "a function type that has a _cv-qualifier-seq_ is not a cv-qualified type; there are no cv-qualified function types." – Jonathan Wakely Aug 06 '13 at 00:01