Я хочу создать std::vector
из std::tuple
(std::vector<std::tuple<Ts...>>
) из двух std::vector
, переместив данные std::vector
s.
Давайте предположим, что у меня есть структура, подобная этой (добавлено std::cout
s для демонстрации проблемы).
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+
для rvalue ссылок 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
?