Per [conv.ptr] / 1 (here N4296):
The null pointer constant is an integer literal (2.13.2) with a value of 0 or the value of the class std::nullptr_t .... The constant of a null pointer of an integral type can be converted to a prvalue of type std::nullptr_t .
shared_ptr has an implicit constructor that takes std::nullptr_t per [util.smartptr.shared.const] / 1:
constexpr shared_ptr(nullptr_t) noexcept : shared_ptr() { }
which creates an empty, not owning shared_ptr .
When you call f(0) directly, 0 is a null pointer constant that is implicitly converted to shared_ptr<int> by the constructor above. When you call call_f(f, 0) , the literal type 0 is call_f(f, 0) to int , and of course, int cannot be converted to shared_ptr<int> .
Casey source share