考虑:
struct A { bool operator==(const A& that) { return true; } };
boost::optional<A&> f()
{
std::vector<A> vec;
auto it = std::find(vec.begin(), vec.end(), A());
// Version A
return (it == vec.end() ? nullptr : *it);
// Version B
if (it == vec.end()) {
return nullptr;
} else {
return *it;
}
}
为什么版本A没有编译(错误C2446:&#39;:&#39;:没有从&#39; A&#39;转换为&#39; nullptr&#39;)而版本B呢?< / p>
(我知道我可以这样做。
return (it == vec.end() ? boost::optional<A&>() : *it);
,我的问题是:为什么nullptr的构造显然与三元运算符区别对待?)
仅在msvc12(= Visual Studio 2013)上测试。
答案 0 :(得分:7)
标准5.16中的三元运算符规则
如果第二个和第三个操作数具有不同的类型,并且具有 (可能是cv-qualified)类类型,或者两者都是glvalues的类 相同的价值类别和相同的类型,除了cv-qualification,an 尝试将每个操作数转换为类型 其他
...
否则(如果E1或E2具有非类型,或者它们都具有 类类型,但底层类不一样,也不是 另一个的基类):如果E1可以,E1可以转换为匹配E2 被隐式转换为申请后E2所具有的类型 左值到右值(4.1),数组到指针(4.2)和 函数到指针(4.3)标准转换。
A
无法隐式转换为nullptr
而nullptr
无法隐式转换为A
。
编译第二个版本,因为从nullptr
到optional
有一些隐式转换。