Erich Keane
erich.keane@intel.com
std::string s = otherstring;
std::vector<int> vect = othervect;
std::vector<double> doubleVect = SomeFunc(args);std::string s = otherstring;
std::vector<int> vect = othervect;
std::vector<double> doubleVect = SomeFunc(args);
namespace std {
template <typename T> // others omitted
class vector {
[...]
public:
vector(const vector<T>& other):size(other.size),
capacity(other.size) {
data = (T*)malloc(sizeof(T) * size); // Expensive!
for (size_t i = 0; i < size; ++i)
data[i] = other[i]; // potentially expensive!
}
[...]
private:
T* data;
size_t size;
size_t capacity;
[...]
};
}std::vector<SomeClass> doubleVect = SomeFunc(args);
// Will Do:
// std::vector ctor inside SomeFunc
// std::vector copy ctor to doubleVect
// std::vector dtor for the temporary
vector(vector<T>&& other) : size(other.size), // move construction
capacity(other.capacity), data(other.data) {
other.data = nullptr;
}
vector& operator=(vector<T>&& other); // move assignment!namespace std { template <typename T>class unique_ptr{
unique_ptr(){...}; // can create empty
unique_ptr(T* target){...}; // can create from a pointer (to own!)
~unique_ptr(){...}; // calls 'delete' on target
unique_ptr(const unique_ptr& other)= delete; // Not allowed, would be multiple owners!
unique_ptr(unique_ptr&& other){...}; // allowed, steals from 'other'
unique_ptr& operator=(const unique_ptr& other) = delete;
unique_ptr& operator=(unique_ptr&& other){...};
};}
// Can not copy 2 unique_ptrs:
unique_ptr<int> i, j;
i = j; // compile error
unique_ptr<int> k = j; // compile error
// function def is unique_ptr<int> make_some_int()
unique_ptr<int> m = make_some_int(); // transfers ownership!class Foo{
public:
// rhs is bound to a RValue,
// HOWEVER, 'rhs' is a named LValue!
Foo(Foo&& rhs) : std::move(rhs._str){}
private: std::string _str;
};
void some_func() {
unique_ptr<int> p, q;
p = q; // compile error
p = std::move(q); // fine!
do_thing(q); // not a compile error, but DEFINITELY a bug!
class Foo{
public:
// rhs is bound to a RValue,
// HOWEVER, 'rhs' is a named LValue!
Foo(Foo&& rhs) : std::move(rhs._str){}
template<typename T1, typename T2>
Foo(T1&& leftArg, T2&& rightArg){...}
private: std::string _str;
};
class Foo{
public:
// rhs is bound to a RValue,
// HOWEVER, 'rhs' is a named LValue!
Foo(Foo&& rhs) : std::move(rhs._str){}
template<typename T1, typename T2>
Foo(T1&& leftArg, T2&& rightArg):
_str1(std::forward<T1>(leftArg), _str2(std::forward<T2>(rightArg){}
private: std::string _str1;
private: std::string _str2;
};template <class T>
constexpr T&& forward(typename remove_reference<T>::type& t) noexcept{
return static_cast<T&&>(t);
}
template <class T>
constexpr T&& forward(typename remove_reference<T>::type&& t) noexcept{
return static_cast<T&&>(t);
}template <typename T>
void Foo (T&& arg){} // For LValues, T is T&
// For RValues, T is T
Shmoo i;
Foo(i); // "T" above is int&
// (function takes reference to a reference of Shmoo,
// folds to a single reference to Shmoo)
Foo(std::move(i)); // "T" above is just "Shmoo" (function takes an RValue reference
// to Shmoo)template <class T> T&& forward(typename remove_reference_t<T>& t) {return static_cast<T&&>(t);}
template <class T> T&& forward(typename remove_reference_t<T>&& t) {return static_cast<T&&>(t);}
// Passing an LValue, "T" is "T&", so ends up being:
T&&& forward(typename remove_reference_t<T&>& t){return static_cast<T&&&>(t);}
// Collapsed to:
T& forward(typename remove_reference_t<T>& t){return static_cast<T&>(t);}
// Passing an Value, "T" is still "T", so ends up being (2nd Overload):
T&& forward(typename remove_reference_t<T>&& t){return static_cast<T&&>(t);}
Erich.Keane@intel.com