C++ 从int到shared_ptr的隐式转换
考虑以下代码:C++ 从int到shared_ptr的隐式转换,c++,c++11,type-conversion,shared-ptr,implicit-conversion,C++,C++11,Type Conversion,Shared Ptr,Implicit Conversion,考虑以下代码: #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
#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
}
我的问题是:
f(0)
中如何执行从int
到std::shared\u ptr
的转换,因为看起来std::shared\u ptr
只有显式构造函数李>
PS:这个例子的变体出现在Scott Meyers的“有效的现代C++项目8”中,作为一种保护方法,用“代码> NulLPTR < /C> > < /P> < P>每[UNI.PTR] / 1(引用N429 6)(<4/6): 空指针常量是值为零的整数文本(2.13.2)或类型为
std::nullptr\t
的prvalue。。。整数类型的空指针常量可以转换为std::nullptr\u t
类型的prvalue
shared\u ptr
有一个非显式构造函数,它根据[util.smartptr.shared.const]/1接受std::nullptr\u t
:
constexpr shared_ptr(nullptr_t) noexcept : shared_ptr() { }
它构造了一个空的、非所有的共享\u ptr
直接调用f(0)
时,0
是一个空指针常量,由上述构造函数隐式转换为shared_ptr
。当您改为调用call_f(f,0)
时,文本0的类型被推断为int
,当然int
不能转换为共享的\u ptr
具有采用std::nullptr\t的构造函数,文字>代码> 0代码>代码是一个空指针常数,它可从C++标准部分草案<代码> 4.10代码> [CON.PTR](强调前进的)转换到:
空指针常量是整数类型的整型常量表达式(5.19)prvalue,其计算结果为零或类型为prvalue
std::nullptr\u t。空指针常量可以转换为
指针类型;结果是该类型的空指针值,为
与对象指针或函数的其他值不同
指针类型。这种转换称为空指针转换。
相同类型的两个空指针值应相等。这个
将空指针常量转换为cv限定的指针
类型是单个转换,而不是指针序列
转换之后是资格转换(4.4)空值
整数类型的指针常量可以转换为PRV值
类型std::nullptr\u t。[注意:结果prvalue不是空值
指针值。-结束注释]
在第二种情况下,p
被推断为int类型,尽管其值为零,但它不再是空指针常量,因此不适合相同的情况
正如T.C.所指出的,措辞发生了变化,需要一个值为零的整型文字,而不是一个计算结果为零的整型常量表达式:
空指针常量是带值的整数文本(2.14.2)
零或std::nullptr\t类型的PR值。空指针常量
可以转换为指针类型;结果是空指针
该类型的值,并可与
对象指针或函数指针类型
第一个调用f(0)被编译为f(nullptr),这对编译器来说很好(但我认为不应该是这样)。第二个调用将为一个函数创建一个声明来处理任何int,这是非法的
有趣的是,即使是这样的代码也能工作:
f(3-3);
f(3*0);
@@vsoftco您应该提到,它仅适用于
f(0)
,除了零之外,没有任何内容正在编译,即使在第一次调用中,其他值也会出现相同的错误。提示说明-“存在从nullptr到任何指针类型的null指针值和任何指向成员类型的指针的隐式转换。std::nullptr__t类型的任何值以及null指针常量宏null都存在类似的转换。”但如果能用标准的参考资料和更清晰的解释,那将是一件有趣的事情。@RupeshYadav。完成。确实,这很奇怪,看起来某种隐式指针转换是有穿透力的。当然,答案是有趣的。在C++中,零是非常可转换的,F(false)和F(′0)之类的东西应该也能正常工作。是的,读完上面的答案是有意义的。代码f(3-3)
正常,因为3-3
或3*0
是一个评估为0的PR值。“空指针常量是一个整数类型的积分常量表达式(5.19)prvalue,其计算结果为零或类型为std::nullptr_t。”另一方面,int x=0;f(x)
不再有效,因为x
不再是PR0值,而是左值,因此不再是空指针常量。可能需要使用更更新的草稿(请参见下面的@Casey答案)。IIRC“计算结果为零的整数类型的整数常量表达式(5.19)prvalue”包括(3*5+8-7)/4-4
,对于涉及非类型模板参数的非依赖调用,它与重载解析进行了奇怪的交互,因此他们仅在DR中将其更改为文字零。@BenVoigt似乎是这样,虽然我同意,但我更喜欢文字上的零。也许暂时支持积分常量表达式作为扩展会有所帮助。
f(3-3);
f(3*0);