如何让编译器推导出一种nullptr类型?
我正在学习C++。 我想让编译器将nullptr推断为shared_ptr。 请仔细阅读下面的代码,如何让编译器推导出一种nullptr类型?
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>
。
非常感谢。
使用条件操作员从nullptr
为 “任何” 强制转换:
auto GetSharedPtrClassB(Tag* tag) {
return tag ? tag->b->a : nullptr;
}
转换,从一个操作数到另一个条件运算符是明确的(见[expr.con d]),这里nullptr
被转换为decltype(tag->b->a)
类型的对象。
在另一方面,使用auto
末尾没有返回类型时返回类型推演规则非常严格 - 推导的类型必须为每个return
声明相同([dcl.spec.auto/9] ):
如果与含有一个占位符类型声明的返回类型的函数有多个return语句, 返回类型推断出每个return语句。如果推导出的类型在每个扣除中不相同,则该程序是不合格的。
如果你的功能不能被减少到有条件的操作,您可以使用尾随返回类型:
auto GetSharedPtrClassB(Tag* tag) -> decltype(tag->b->a) {
if (tag) {
auto& sharedB = *(tag->b);
return sharedB.a;
} else {
return {};
}
}
您可以改为返回默认构造的shared_ptr。
auto GetSharedPtrClassB(Tag* tag) {
if (tag) {
auto& sharedB = *(tag->b);
return sharedB.a;
} else {
return std::shared_ptr<A>{};
}
}
:谢谢你的评论吧。在我的实际代码中,类A可以是C,因为元编程。所以我想让推导出shared_ptr类型的。 – mora
@mora - 对不起,是AFK。霍尔特的回答正是你应该做的增加扣除。我建议你接受这个答案。 – StoryTeller
这是我更少的解释。你的答案是我的一个解决方案。谢谢你再次回答。 – mora
您可以使用static_cast
这样的:
auto GetSharedPtrClassB(Tag* tag) {
if (tag) {
auto& sharedB = *(tag->b);
return sharedB.a;
} else {
return static_cast<std::shared_ptr<A> >(nullptr);
}
}
:谢谢你的评论。在我的实际代码中,类A可以是C,因为元编程。所以我想让推导出shared_ptr类型的。 – mora
好的错过了...... –
我会假设你的代码在一个通用的背景下实际使用。如果你的代码不使用模板,不要使用decltype,直接指定类型。
要推导返回类型,所有返回语句必须求值为相同类型的表达式。在你的代码中,你有两个不同类型的返回语句。一个与std::shared_ptr<A>
,一个与std::nullptr_t
。
有两种解决方法:在两个return语句中使用相同的类型,或者明确定义返回类型。
这里是如何返还相同种类:
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;
谢谢你告诉我两种使用decltype的方法。 – mora
如何关于明确使用'std :: shared_ptr '作为返回类型?或者在'else'情况下返回一个默认构造的'std :: shared_ptr '对象? –
@Someprogrammerdude:谢谢你的评论。在我的实际代码中,类A可以是C,因为元编程。所以我想让推导出shared_ptr类型的。 – mora
这是更好地展示实际的问题,因为现在每个人都需要猜测哪种方法最适合([XY问题(https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)) ...另请参阅如何提出一个很好的问题:MCVE(https://stackoverflow.com/help/mcve) –