c++ - boost 可选和用户定义的转换

标签 c++ c++11 boost type-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 结构构造函数而不是使用用户定义的转换运算符?

您可以直接将我指向 user-defined conversion 的任何位置页面,因为我找不到任何原因。例如,

User-defined conversion function is invoked on the second stage of the implicit conversion, which consists of zero or one converting constructor or zero or one user-defined conversion function.

在我看来直接说如果没有定义转换构造函数那么将使用用户定义的转换函数。我错了吗?如果是,我如何在 struct A 中定义转换 cunstructor 的情况下实现用户定义的转换?

最佳答案

您的代码有两个问题。你的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);

这还有一个额外的好处,那就是更易于阅读。

关于c++ - boost 可选和用户定义的转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33282082/

相关文章:

c++ - boost::asio::async_read 在不满足完成条件的情况下结束

c++ - 将 boost::posix_time::time_duration boost 为字符串

c++ - 什么是 do(keyword) c++?

c++ - 系统(“pause”)即使使用正确的 header 也不起作用

c++ - 如何使用不同线程访问单例类成员函数?

c++ - 大括号的数量如何影响统一初始化?

c++ - Protobuf 版本冲突

c++ - 为什么 Cmake 不能使用 include_directories 找到库?

C++11 初始化 std::string 成员

boost - 如何自定义Boost.Log的 "TimeStamp"格式