mich korrigieren, wenn ich falsch bin, aber wennImplementierung tief Kopieren von Tupel von Zeigern
std::tuple<double*, bool*> t(new double(3.5), new bool(true));
print_tuple(t);
std::tuple<double*, bool*> n = t;
print_tuple(n);
I
std::get<0>(t) = 0x1f13d0
std::get<1>(t) = 0x1f13b0
std::get<0>(n) = 0x1f13d0
std::get<1>(n) = 0x1f13b0
zum Laufen bringen, die die Zeiger in der Tupel bedeutet nur seichte kopiert, Recht? Also schrieb ich ein einfaches Dienstprogramm, das zu tiefer Kopie gemeint ist, alle Elemente eines Tupels, die Zeiger sind:
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>{});
}
Und dies scheint für das Beispiel gut zu funktionieren oben, aber wenn ich es mit Tupel versuche tup
definiert durch
Ich bekomme eine tiefe Kopie des Tupelzeigers, aber die Zeiger innerhalb des Tupelzeigers werden wieder flach kopiert. Ich möchte, dass diese Zeiger auch tief kopiert werden. Wie behebt man dies für eine beliebige Anzahl von verschachtelten Tupel von Zeigern? Hier sind meine Testergebnisse:
#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));
}
Ausgang:
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
Ich bin nicht so vertraut, aber ich vermute, dass Sie 'depp_copy' in' deep_copy_impl' rekursiv aufrufen müssen, wenn das aktuelle Tupel-Element selbst ein Tupel ist. –
Ah! Ich werde es versuchen. Dies könnte dann eine teilweise Spezialisierung von Strukturen erfordern. – prestokeys
posten Sie die Antwort, wenn Sie es herausfinden! Ich bin gespannt, wie es ausgeht;) Eigentlich T.C. Lösung scheint ziemlich elegant. –