2

Not exactly a question but more of a musing... I wrote a program to test how 'std::bind' passes arguments to the function being binded. It seems like in this instance the C++ compiler performs static type checking:

#include <iostream>
#include <functional>

void take_int(const int *a)
{
    if (a)
    {
        std::cout << "a is " << *a << std::endl;
    }
    else
    {
        std::cout << "null" << std::endl;
    }
}

int main()
{
    int *a = new(int);
    *a = 4;
    take_int(NULL); //prints 'null'
    auto fn = std::bind(take_int, NULL); //fails to compile
    fn();
    return 0;
}

It seems inconsistent to be able to directly call the function with NULL but for it to fail at compile time when doing so through std::bind.

I guess std::bind is using more modern C++ features which chooses to enforce this?

laker93
  • 498
  • 4
  • 9

2 Answers2

5

This is because you are using NULL, which is deprecated. Instead, you should be using nullptr.

If you use nullptr in your snipped, code compiles as expected.

You need to keep in mind that

NULL can be an integer literal with value zero, or a prvalue of type std::nullptr_t

In your case, it is integer literal. When you call a function with that value, it is converted to pointer - this is why calling a function directly works.

SergeyA
  • 61,605
  • 5
  • 78
  • 137
  • You say that "When you call a function with that value, it is converted to pointer - this is why calling a function directly works." Is this not what I'm doing with std::bind? I am calling a function with a NULL value. Why is it that in this case NULL is not converted to a pointer? – laker93 Aug 31 '18 at 14:52
  • @LukePurnell, no, because this implicit conversion to pointer only exists for literal 0. But bind works with types, so it tries to find a function which accepts integer types - and integer types are not implicitly convertible to pointers. This is all a result of this special quirk, of integers not convertible to pointers, except for 0 literal. – SergeyA Aug 31 '18 at 14:56
  • 2
    _Is that not what I'm doing with std::bind?_ No - look at the prototype for [`std::bind`](https://en.cppreference.com/w/cpp/utility/functional/bind). The types of `Args...` are deduced to be exactly what you passed - it has no way to know you wanted it to apply an implicit conversion as if to `take_int(const int*)`. – Useless Aug 31 '18 at 15:00
3

Your Compiler defines NULL as 0 which as a literal can be implicitly converted to an int*. Thats why your first call is succesful. But std::bind() will generate an object for <void (&)(const int *),int> which can't be called since a variable of type int cannot be implicitly converted to int*.

Swordfish
  • 12,971
  • 3
  • 21
  • 43