Consider the code below:
#include
#include
void f(std::shared_ptr sp) {}
template
Per [conv.ptr]/1 (quoting N4296 here):
A null pointer constant is an integer literal (2.13.2) with value zero or a prvalue of type
std::nullptr_t. ... A null pointer constant of integral type can be converted to a prvalue of typestd::nullptr_t.
shared_ptr has a non-explicit constructor that accepts std::nullptr_t per [util.smartptr.shared.const]/1:
constexpr shared_ptr(nullptr_t) noexcept : shared_ptr() { }
which constructs an empty, non-owning shared_ptr.
When you call f(0) directly, 0 is a null pointer constant that is implicitly converted to shared_ptr by the above constructor. When you instead call call_f(f, 0), the type of the literal 0 is deduced to int and of course an int cannot be converted to a shared_ptr.