Là một theo dõi, tôi đến workaround này:
template<class T>
struct mover
{
mover(T const& val) : val(val) {}
mover(T&& val) : val(std::move(val)) {}
mover(mover const& other) = default;
mover(mover&& other) = default;
mover(mover& other) : val(std::move(other.val)) {}
operator T const&() const
{
return val;
}
T val;
};
template<class T>
using wrap_t = typename std::conditional
<
std::is_move_constructible<T>::value
&& !std::is_trivially_copy_constructible<T>::value
, mover<T>
, T
>::type;
template<class... Ts>
auto pack_impl(wrap_t<Ts>... ts)
{
return [=](auto&& f)->decltype(auto)
{
return f(static_cast<Ts const&>(ts)...);
};
}
auto pack = [](auto&&... ts)
{
return pack_impl<std::decay_t<decltype(ts)>...>(static_cast<decltype(ts)>(ts)...);
};
Nó sử dụng mover
làm proxy, cho phép lambda nắm bắt nó bằng cách di chuyển (đó là một chút hacky). Và wrap_t
quyết định khi nào là cần thiết hoặc có lợi để áp dụng mover
.
Bây giờ chúng ta có thể kiểm tra nó:
struct A
{
A() = default;
A(A&&)
{
std::cout << "move\n";
}
A(A const&)
{
std::cout << "copy\n";
}
};
A a;
std::cout <<"p1------------\n";
auto p1 = pack(std::move(a));
std::cout <<"p2------------\n";
auto p2 = std::move(p1);
std::cout <<"p3------------\n";
auto p3 = p2;
Sẽ in:
p1------------
move
move
p2------------
move
p3------------
copy
Bạn đang gặp phải vấn đề gì khi chụp '&' và sử dụng 'f (std :: move (t) ...)'? – chris
@chris Các tài liệu tham khảo sẽ trở nên lúng túng ngay khi 'gói' trả về, không? – Brian
@Brian, Oh yeah, điểm tốt. Tôi không nhận thấy nó đã được trả lại. – chris