从int到shared_ptr的隐式转换

vso*_*tco 6 c++ type-conversion shared-ptr implicit-conversion c++11

请考虑以下代码:

#include <iostream>
#include <memory>

void f(std::shared_ptr<int> sp) {}

template <typename FuncType, typename PtrType>
auto call_f(FuncType f, PtrType p) -> decltype(f(p))
{
    return f(p);
}

int main()
{
    f(0); // doesn't work for any other int != 0, thanks @Rupesh
    // call_f(f, 0); // error, cannot convert int to shared_ptr
}
Run Code Online (Sandbox Code Playgroud)

在第一行中main(),整数0转换为a std::shared_ptr<int>,调用f(0)成功,没有任何问题.但是,使用模板调用函数会使事情变得不同.第二行将不再编译,错误是

error: could not convert 'p' from 'int' to 'std::shared_ptr<int>'
Run Code Online (Sandbox Code Playgroud)

我的问题是:

  1. 为什么第一次通话成功而第二次通话没有?这里有什么我想念的吗?
  2. 我不也明白如何从转换intstd::shared_ptr被调用执行f(0),因为它看起来像std::shared_ptr只有明确的构造函数.

PS:这个例子的一个变体出现在Scott Meyers的Effective Modern C++ Item 8中,作为一种保护这种调用的方式nullptr.

Sha*_*our 5

std :: shared_ptr有一个构造函数,它接受std :: nullptr_t,literal 0是一个空指针常量,可以从草案C++标准部分[conv.ptr]转换为std :: nullptr_t(强调我的前进):4.10

空指针常量是整数类型的整数常量表达式(5.19)prvalue,其计算结果为零或类型为std :: nullptr_t的prvalue.空指针常量可以转换为指针类型; 结果是该类型的空指针值,并且可以与对象指针或函数指针类型的每个其他值区分开.这种转换称为空指针转换.相同类型的两个空指针值应相等.将空指针常量转换为指向cv限定类型的指针是单个转换,而不是指针转换的序列,后跟限定转换(4.4).可以将整数类型的空指针常量转换为std :: nullptr_t类型的prvalue.[注意:生成的prvalue不是空指针值. - 尾注]

在你的第二种情况下p推断为int类型,虽然值为零但不再是空指针常量,因此不适合相同的情况.

正如TC指出的那样,措辞是用DR 903改变的,它需要一个值为零的整数文字,而不是一个计算为零的整数常量表达式:

空指针常量是值为零整数文字(2.14.2)或类型为std :: nullptr_t的prvalue.空指针常量可以转换为指针类型; 结果是该类型的空指针值,并且可以与对象指针或函数指针类型的每个其他值区分开.