【发布时间】:2016-05-03 23:35:39
【问题描述】:
如果我错了,请纠正我,但是在运行时
std::tuple<double*, bool*> t(new double(3.5), new bool(true));
print_tuple(t);
std::tuple<double*, bool*> n = t;
print_tuple(n);
我明白了
std::get<0>(t) = 0x1f13d0
std::get<1>(t) = 0x1f13b0
std::get<0>(n) = 0x1f13d0
std::get<1>(n) = 0x1f13b0
这意味着元组中的指针只是浅拷贝的,对吗?因此,我编写了一个简单的实用程序,旨在深度复制元组中作为指针的所有元素:
template <std::size_t N, typename Tuple>
std::enable_if_t<std::is_pointer<std::tuple_element_t<N, Tuple>>::value> assign (Tuple& tuple, const Tuple& other) {
std::get<N>(tuple) = new std::remove_pointer_t<std::tuple_element_t<N, Tuple>>(*std::get<N>(other));
}
template <std::size_t N, typename Tuple>
std::enable_if_t<!std::is_pointer<std::tuple_element_t<N, Tuple>>::value> assign (Tuple& tuple, const Tuple& other) {
std::get<N>(tuple) = std::get<N>(other);
}
template <typename Tuple, std::size_t... Is>
Tuple deep_copy_impl (const Tuple& other, std::index_sequence<Is...>) {
Tuple tuple = {};
const int a[] = {(assign<Is>(tuple, other), 0)...};
static_cast<void>(a);
return tuple;
}
template <typename Tuple>
Tuple deep_copy (const Tuple& other) {
return deep_copy_impl(other, std::make_index_sequence<std::tuple_size<Tuple>::value>{});
}
对于上面的示例,这似乎可以正常工作,但是当我使用由定义的元组 tup 尝试它时
std::tuple<double*, bool*> t(new double(3.5), new bool(true));
std::tuple<int*, std::tuple<double*, bool*>*, char> tup(new int(5), &t, 'a');
我得到了元组指针的深拷贝,但是元组指针中的指针又被浅拷贝了。我希望这些指针也能被深度复制。如何为任意数量的嵌套指针元组解决这个问题?这是我的测试结果:
#include <iostream>
#include <type_traits>
#include <utility>
#include <tuple>
template <std::size_t N, typename Tuple>
std::enable_if_t<std::is_pointer<std::tuple_element_t<N, Tuple>>::value> assign (Tuple& tuple, const Tuple& other) {
std::get<N>(tuple) = new std::remove_pointer_t<std::tuple_element_t<N, Tuple>>(*std::get<N>(other));
}
template <std::size_t N, typename Tuple>
std::enable_if_t<!std::is_pointer<std::tuple_element_t<N, Tuple>>::value> assign (Tuple& tuple, const Tuple& other) {
std::get<N>(tuple) = std::get<N>(other);
}
template <typename Tuple, std::size_t... Is>
Tuple deep_copy_impl (const Tuple& other, std::index_sequence<Is...>) {
Tuple tuple = {};
const int a[] = {(assign<Is>(tuple, other), 0)...};
static_cast<void>(a);
return tuple;
}
template <typename Tuple>
Tuple deep_copy (const Tuple& other) {
return deep_copy_impl(other, std::make_index_sequence<std::tuple_size<Tuple>::value>{});
}
// Testing
template <typename Tuple, std::size_t... Is>
std::ostream& print_tuple_impl (const Tuple& tuple, std::ostream& os, std::index_sequence<Is...>) {
const int a[] = {(os << "std::get<" << Is << ">(tuple) = " << std::get<Is>(tuple) << '\n', 0)...};
static_cast<void>(a);
return os;
}
template <typename Tuple>
std::ostream& print_tuple (const Tuple& tuple, std::ostream& os = std::cout) {
return print_tuple_impl (tuple, os, std::make_index_sequence<std::tuple_size<Tuple>::value>{});
}
int main() {
std::tuple<double*, bool*> t(new double(3.5), new bool(true));
print_tuple(t);
std::tuple<double*, bool*> n = t;
print_tuple(n);
std::cout << "Above is shallow copying only.\n\n";
std::tuple<int*, std::tuple<double*, bool*>*, char> tup(new int(5), &t, 'a');
print_tuple(tup);
std::tuple<int*, std::tuple<double*, bool*>*, char> q = deep_copy(tup);
print_tuple(q);
std::cout << "\nAbove seems like a deep copy, but look at this:\n";
print_tuple(*std::get<1>(tup));
print_tuple(*std::get<1>(q));
}
输出:
std::get<0>(tuple) = 0x1f13d0
std::get<1>(tuple) = 0x1f13b0
std::get<0>(tuple) = 0x1f13d0
std::get<1>(tuple) = 0x1f13b0
Above is shallow copying only.
std::get<0>(tuple) = 0x1f13f0
std::get<1>(tuple) = 0x72fe10
std::get<2>(tuple) = a
std::get<0>(tuple) = 0x1f1410
std::get<1>(tuple) = 0x1f1430
std::get<2>(tuple) = a
Above seems like a deep copy, but look at this:
std::get<0>(tuple) = 0x1f13d0
std::get<1>(tuple) = 0x1f13b0
std::get<0>(tuple) = 0x1f13d0
std::get<1>(tuple) = 0x1f13b0
【问题讨论】:
-
我对这个不太熟悉,但我怀疑如果当前的元组元素本身就是一个元组,你需要在
deep_copy_impl中递归调用depp_copy。 -
啊!我会试试的。这可能需要结构的部分特化。
-
如果你能弄明白,请发布答案!我很想知道结果如何;)实际上 T.C.解决方案看起来很优雅。
-
@dau_sama 是的,T.C. 的解决方案非常优雅。您可能对我如何将 T.C. 的解决方案扩展到 STL 容器感兴趣。
标签: c++ tuples c++14 variadic-templates deep-copy