我正在学习c++。我希望让编译器将nullptr推断为shared_ptr。请阅读以下代码,
struct A {};
struct B {
std::shared_ptr<A> a;
};
struct Tag {
std::shared_ptr<B> b;
};
auto GetSharedPtrClassB(Tag* tag) {
if (tag) {
auto& sharedB = *(tag->b);
return sharedB.a;
} else {
return nullptr; // Error : compiler cannot deduce type of nullptr.
}
}在GetSharedPtrClassB中,nullptr不能被推断为std::shared_ptr<A>。错误消息如下,
error: inconsistent deduction for ‘auto’: ‘std::shared_ptr<A>’ and then ‘std::nullptr_t’如何让编译器将nullptr推断为std::shared_ptr<A>?我可以提供一个类型的decltype(*(tag->b)),但我想不出下一步提供std::shared_ptr<A>类型的步骤。
非常感谢。
发布于 2017-06-12 14:21:00
使用条件运算符强制将nullptr转换为“任何”:
auto GetSharedPtrClassB(Tag* tag) {
return tag ? tag->b->a : nullptr;
}在条件运算符中,从一个操作数转换到另一个操作数是非常明确的(参见expr.cond),在这里,nullptr被转换为decltype(tag->b->a)类型的对象。
另一方面,在使用没有尾随返回类型的auto时,返回类型的演绎规则非常严格--对于每个return语句(dcl.spec.Auto/9),推导的类型必须是相同的:
如果包含占位符类型的声明返回类型的函数有多个返回语句,则为每个返回语句推导返回类型。如果推导的类型在每个演绎中不相同,则程序是错误的。
如果不能将函数简化为条件运算符,则可以使用尾随返回类型:
auto GetSharedPtrClassB(Tag* tag) -> decltype(tag->b->a) {
if (tag) {
auto& sharedB = *(tag->b);
return sharedB.a;
} else {
return {};
}
}发布于 2017-06-12 14:18:22
您可以返回默认构造的shared_ptr。
auto GetSharedPtrClassB(Tag* tag) {
if (tag) {
auto& sharedB = *(tag->b);
return sharedB.a;
} else {
return std::shared_ptr<A>{};
}
}发布于 2017-06-12 14:26:08
我假设您的代码实际上是在泛型上下文中使用的。如果您的代码不使用模板不使用解密类型,请直接指定类型。
若要推断返回类型,所有返回语句都必须计算为相同类型的表达式。在您的代码中,有两个具有两种不同类型的返回语句。一个用std::shared_ptr<A>,一个用std::nullptr_t。
有两种解决方案:在两个返回语句中使用相同的类型,或者显式定义返回类型。
下面是如何返回相同类型的内容:
auto GetSharedPtrClassB(Tag* tag) {
if (tag) {
auto& sharedB = *(tag->b);
return sharedB.a;
}
// empty constructor same as initializing with `nullptr`
return decltype(tag->b->a){};
}或显式定义返回类型:
auto GetSharedPtrClassB(Tag* tag) -> decltype(tag->b->a) {
if (tag) {
auto& sharedB = *(tag->b);
return sharedB.a;
}
// empty constructor same as initializing with `nullptr`
return {};
}顺便说一句,在您的代码中,auto& sharedB = *(tag->b); return sharedB.a;可以简化为return tag->b->a;
https://stackoverflow.com/questions/44501629
复制相似问题