std::uninitialized_copy
copies into an uninitialized range of memory. This could be done using std::memmove
for bitwise copyable types. I stepped through below example code in gdb (compiling with gcc 5.2.0). Thereby I observed that __is_trivial(Bar)
is used to determine whether memmove
may be used. It (correctly) evaluates to false
as Bar
has a non-trivial default constructor (cf. call to std::__uninitialized_copy<false>::__uninit_copy(...)
in bits/stl_uninitialized.h
line 123
ff).
But why is __is_trivial
even relevant to std::uninitialized_copy
? According to Bjarne std::is_trivially_copy_constructible
should be sufficient. Note that the latter evaluates to true
in the example, ie. the memmove
optimization is applicable.
I'm aware, that the standard does not require any specific implementation of std::uninitialized_copy
. I'm just wondering why __is_trivial
is favored even if std::is_trivially_copy_constructible
is present as an applicable alternative to the gcc implementation?
Example Code:
#include <iostream>
#include <vector>
#include <type_traits>
struct Bar
{
Bar () : v(17) {};
Bar(Bar const &) = default;
Bar(Bar &&) = default;
Bar & operator=(Bar &&) = default;
Bar & operator=(Bar const &) = default;
int v;
};
int main() {
std::cout
<< std::is_trivially_move_constructible<Bar>::value
<< " " << std::is_trivially_copy_constructible<Bar>::value
<< " " << std::is_trivially_copyable<Bar>::value
<< " " << std::is_trivial<Bar>::value
<< " " << __is_trivial(Bar) << std::endl;
std::vector<Bar> v(10);
Bar * vc = new Bar[10];
std::uninitialized_copy(v.begin(), v.end(), vc);
delete[] vc;
}
Example Output: 1 1 1 0 0
Aucun commentaire:
Enregistrer un commentaire