mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-15 14:16:07 -06:00
65 lines
1.6 KiB
C++
65 lines
1.6 KiB
C++
#include "Tutorial.h"
|
|
#include <vector>
|
|
|
|
void Transfer()
|
|
{
|
|
/// .Transfer issues
|
|
|
|
/// Often you need to pass content of one container to another of the same type. U++
|
|
/// containers always support ^topic://Core/srcdoc/pick_$en-us:pick semantics^ (synonym of
|
|
/// std::move), and, depending on type stored, also might support
|
|
/// ^topic://Core/srcdoc/pick_$en-us:clone semantics^. When transferring the value, you
|
|
/// have to explicitly specify which one to use:
|
|
|
|
Vector<int> v{ 1, 2 };
|
|
|
|
DUMP(v);
|
|
|
|
Vector<int> v1 = pick(v);
|
|
|
|
DUMP(v);
|
|
DUMP(v1);
|
|
|
|
/// now source `Vector` `v` is empty, as elements were 'picked' to `v1`.
|
|
|
|
/// If you really need to preserve value of source (and elements support deep copy
|
|
/// operation), you can use `clone`:
|
|
|
|
v = clone(v1);
|
|
|
|
DUMP(v);
|
|
DUMP(v1);
|
|
|
|
/// The requirement of explicit `clone` has the advantage of avoiding unexpected deep
|
|
/// copies. For example:
|
|
|
|
Vector<Vector<int>> x;
|
|
x.Add() << 1 << 2 << 3;
|
|
|
|
#if 0
|
|
for(auto i : x) { LOG(i); }
|
|
#endif
|
|
|
|
/// results in run-time error, whereas the equivalent code with `std::vector` compiles but
|
|
/// silently performs deep copy for each iteration:
|
|
|
|
#if 0
|
|
std::vector<std::vector<int>> sv;
|
|
sv.push_back({1, 2, 3});
|
|
for(auto i : sv) // invokes std::vector<int> copy constructor
|
|
for(auto j : i)
|
|
DUMP(j);
|
|
#endif
|
|
|
|
/// That said, in certain cases it is simpler to have default copy instead of explicit
|
|
/// `clone`. You can easily achieve that using `WithDeepCopy` template:
|
|
|
|
WithDeepCopy<Vector<int>> v2;
|
|
|
|
v2 = v;
|
|
|
|
DUMP(v);
|
|
DUMP(v2);
|
|
|
|
///
|
|
}
|