[英]boost optional and user-defined conversion
我无法为Item
类型编写正确的用户定义转换。 这是我尝试过的:
#include <iostream>
#include <boost/optional.hpp>
struct A
{
int x;
};
struct Item
{
boost::optional<int> x_;
Item(){}
Item(const A& s)
: x_(s.x)
{
}
operator boost::optional<A>() const {
boost::optional<A> s;
if (x_) {
s->x = *x_;
}
return s;
}
};
std::vector<A> getA(const std::vector<Item> &items) {
std::vector<A> a;
for (const auto &i : items) {
if (i.x_) {
a.push_back(*static_cast<boost::optional<A>>(i)); // <- this line causes error
}
}
return a;
}
那就是我的用法:
int main() {
A a;
a.x = 3;
Item i(a);
auto v = getA({i});
return 0;
}
g++ -std=c++11
说:
In file included from /usr/include/boost/optional.hpp:15:0,
from test.cpp:2:
/usr/include/boost/optional/optional.hpp: In instantiation of ‘void boost::optional_detail::optional_base<T>::construct(const Expr&, const void*) [with Expr = Item; T = A]’:
/usr/include/boost/optional/optional.hpp:262:25: required from ‘boost::optional_detail::optional_base<T>::optional_base(const Expr&, const Expr*) [with Expr = Item; T = A]’
/usr/include/boost/optional/optional.hpp:559:78: required from ‘boost::optional<T>::optional(const Expr&) [with Expr = Item; T = A]’
test.cpp:30:55: required from here
/usr/include/boost/optional/optional.hpp:392:8: error: no matching function for call to ‘A::A(const Item&)’
new (m_storage.address()) internal_type(expr) ;
^
/usr/include/boost/optional/optional.hpp:392:8: note: candidates are:
test.cpp:3:8: note: A::A()
struct A
^
test.cpp:3:8: note: candidate expects 0 arguments, 1 provided
test.cpp:3:8: note: constexpr A::A(const A&)
test.cpp:3:8: note: no known conversion for argument 1 from ‘const Item’ to ‘const A&’
test.cpp:3:8: note: constexpr A::A(A&&)
test.cpp:3:8: note: no known conversion for argument 1 from ‘const Item’ to ‘A&&’
为什么它试图找到A
结构的构造函数,而不是使用用户定义的转换操作符?
您可能会直接将我指向用户定义的转换页的任何位置,因为我找不到任何原因。 例如,
在隐式转换的第二阶段调用用户定义的转换函数,该隐式转换由零个或一个转换构造函数或零个或一个用户定义的转换函数组成。
我认为直接表示如果未定义转换构造函数,则将使用用户定义的转换函数。 我错了吗? 如果是的话,如何在不定义struct A
情况下实现用户定义的转换呢?
您的代码有两个问题。 您的optional
运算符永远不会初始化boost::optional
。 如果不这样做,则访问成员是未定义的行为。 您要做的是:
operator boost::optional<A>() const {
boost::optional<A> s;
if (x_) {
s = A{*x_};
}
return s;
}
第二个问题是您何时执行以下操作:
static_cast<boost::optional<A>>(i);
这等效于:
boost::optional<A> __tmp(i);
但事实证明, boost::optional
具有explicit
模板构造函数。 这将是您的转换功能的首选。 您看到的错误是编译沿着此工厂构造函数的路径进行,而Item
不是这样的工厂。
您可以直接使用boost::optional<A>
:
std::vector<A> getA(const std::vector<Item> &items) {
std::vector<A> a;
for (boost::optional<A> opt : items) {
if (opt) {
a.push_back(*opt);
}
}
return a;
}
或者,由于构造函数模板是explicit
,因此可以在非显式上下文中使用转换运算符:
boost::optional<A> opt = i;
a.push_back(*opt);
这样做还有一个好处,就是易于阅读。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.