c++ - 通过 move 从两个 vector 创建元组 vector

标签 c++ vector tuples c++17 move-semantics

我想创建一个 std::vectorstd::tuple的 ( std::vector<std::tuple<Ts...>> ) 来自两个 std::vector通过 move std::vector 的数据

假设我有一个与此类似的结构(添加了 std::cout 以展示问题)。

template<typename T>
struct MyType
{
    constexpr MyType() { std::cout << "default constructor\n"; }
    constexpr MyType(const T& data) : m_data(data)
    {
        std::cout << "data constructor\n";
    }
    constexpr MyType(const MyType& other) : m_data(other.m_data)
    {
        std::cout << "copy constructor\n"; 
    }

    constexpr MyType(MyType&& other) noexcept : m_data(std::move(other.m_data))
    {
        std::cout << "move constructor\n";
    }
    ~MyType() = default;

    constexpr MyType& operator=(const MyType& other)
    {
        std::cout << "copy operator\n";
        m_data = other.m_data;
        return *this;
    }
    constexpr MyType& operator=(MyType&& other) noexcept
    {
        std::cout << "move operator\n";
        m_data = std::move(other.m_data);
        return *this;
    }

private:
    T m_data{};
};

现在我们可以定义一个operator+ std::vector<MyType<T>> 的右值引用:

template<typename LhsT, typename RhsT>
constexpr auto operator+(std::vector<MyType<LhsT>>&& lhs, std::vector<MyType<RhsT>>&& rhs)
{
    if(lhs.size() != rhs.size())
        throw std::runtime_error("");

    std::vector<std::tuple<MyType<LhsT>, MyType<RhsT>>> ret(lhs.size());

    std::cout << "before transform\n";
    std::transform(std::make_move_iterator(lhs.cbegin()),
                   std::make_move_iterator(lhs.cend()),
                   std::make_move_iterator(rhs.cbegin()),
                   ret.begin(),
                   [](auto&& lhs_val, auto&& rhs_val) {
        return std::make_tuple(lhs_val, rhs_val);
    });
    std::cout << "after transform\n";
    return ret;
}

现在我遇到了这个问题。运行这段代码时

int main()
{
    std::vector<MyType<int>> int_vec(1);
    std::vector<MyType<float>> float_vec(1);

    std::cout << "before move operator+\n";
    auto int_float_tp_vec = std::move(int_vec) + std::move(float_vec);
    std::cout << "after move operator+\n";
}

输出是这样的:

default constructor
default constructor
before move operator+
default constructor
default constructor
before transform
copy constructor
copy constructor
move operator
move operator
after transform
after move operator+

问题是:为什么copy constructor叫什么?正在使用 std::make_tuple这里的错误方法?我如何在不调用 copy constructor 的情况下执行此操作?也不是 copy operator

LIVE DEMO

最佳答案

你忘了在这里使用 std::move:

[](auto&& lhs_val, auto&& rhs_val) {
    return std::make_tuple(std::move(lhs_val), std::move(rhs_val));
});

记住,所有命名的都是左值。

此外,你必须修复你的迭代器:

std::transform(lhs.begin(),
               lhs.end(),
               rhs.begin(),
               ret.begin(),
               [](auto&& lhs_val, auto&& rhs_val) {
    return std::make_tuple(std::move(lhs_val), std::move(rhs_val));
});

您不能从 const 迭代器创建 move 迭代器,这类似于应用于 const 类型的 std::move。事实上,我们可以不用 move 迭代器,只使用左值引用调用我们的 lambda,然后我们可以从它 move 。

关于c++ - 通过 move 从两个 vector 创建元组 vector ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56977339/

相关文章:

R - Grepl 向量上的向量

python - 我如何在这个 Python 作业中将列表、标量和向量联系在一起?

c++ - 具有元组类型子集相应参数的模板函数

python - 元组列表(从元组中删除特殊项目)

c++ - 仅使用 get 或 set 的原始类型的线程安全威胁是否被夸大了?

c++ - std::stringstream 和 str 方法

具有 const 限定符的自由函数类型的 C++ 特化

c++ - 当我尝试读取其他 dialog.ui 的空数据时,Qt c++ 读取访问冲突

python - 这里如何使用reduce函数?

c++ - 如何保存这个 vector 图