Ответ 1
Вы используете подпись tuple< vector<int>, vector<int>, vector<int> >
, которая является временной, и элементы могут быть перемещены, поэтому
std::tie(fact, mean, err) = getAllBlockMeanErrorTuple(vec)
следует переместить-присваивать fact
, mean
и err
.
Вот пример программы для вас, чтобы увидеть себя (demo):
#include <iostream>
#include <vector>
#include <tuple>
struct A
{
A() = default;
~A() = default;
A(const A&)
{
std::cout << "Copy ctor\n";
}
A(A&&)
{
std::cout << "Move ctor\n";
}
A& operator=(const A&)
{
std::cout << "Copy assign\n";
return *this;
}
A& operator=(A&&)
{
std::cout << "Move assign\n";
return *this;
}
};
std::tuple<A, A> DoTheThing()
{
A first;
A second;
return std::make_tuple(first, second);
}
int main()
{
A first;
A second;
std::tie(first, second) = DoTheThing();
}
Вывод:
Скопировать ctor
Копировать ctor
Переместить назначение
Переместить назначение
Обратите внимание: функция должна была создать копии векторов для возврата tuple
, которые могут быть не такими, какие вы хотите. Вы можете захотеть std::move
элементов в std::make_tuple
:
return make_tuple(std::move(fact), std::move(mean), std::move(err));
Здесь тот же пример, что и выше, но с std:: move, используемый в make_tuple
Обратите внимание, что с С++ 17 Structured Bindings вы можете вообще забыть об использовании std::tie
и больше ориентироваться на auto
(Спасибо, @Yakk):
auto[fact, mean, err] = getAllBlockMeanErrorTuple(vec);
Ранние реализации стандарта С++ 17 для clang (3.8.0) и gcc (6.1.0) пока не поддерживают его, однако, похоже, в clang 4.0.0 есть некоторая поддержка: Демо (Спасибо, @Revolver_Ocelot)
Вы заметите, что результат со структурированными привязками изменяется на:
Переместить ctor
Переместить ctor
Указывая на то, что они используют преимущества копирования, которые сохраняют дополнительные операции перемещения.