visual c++ - Does the C++ standard specify STL implementation details for the compiler? -
while writing answer this question faced interesting situation - question demonstrates scenario 1 want put class in stl container fails because of missing copy constructor/move constructor/assignment operator. in particular case error triggered std::vector::resize
. made quick snippet solution , saw answer had provided move constructor instead of assignment operator , copy constructor had. interresting other answer did not compile in vs 2012, while clang/gcc happy both approaches.
first:
// clang , gcc happy one, vs 2012 not #include <memory> #include <vector> class fooimpl {}; class foo { std::unique_ptr<fooimpl> myimpl; public: foo( foo&& f ) : myimpl( std::move( f.myimpl ) ) {} foo(){} ~foo(){} }; int main() { std::vector<foo> testvec; testvec.resize(10); return 0; }
second:
// clang/gcc/vs2012 happy #include <memory> #include <vector> using namespace std; class fooimpl {}; class foo { unique_ptr<fooimpl> myimpl; public: foo() { } ~foo() { } foo(const foo& foo) { // pointer? } foo& operator= (const foo& foo) { if (this != &foo) { // pointer? } return *this; } }; int main(int argc, char** argv) { vector<foo> testvec; testvec.resize(10); return 0; }
to understand happening looked @ stl sources in vs 2012 , saw invoking move assignment operator why sample worked (i don't have linux machine accessible understand going on in clang/gcc) , other did not, since had move copy constructor.
so created following question - can compiler freely decide how implement stl methods (in case std::vector::resize
), since radically different implementations cause non-portable code? or vs 2012 bug?
above all, since c++11, std::vector<>
can store not-copyable types. (example) let's take @ cppreference.
until c++11, t should copyable know.
t must meet requirements of copyassignable , copyconstructible.
however, in c++11, requirements changed.
the requirements imposed on elements depend on actual operations performed on container. generally, required element type complete type , meets requirements of erasable, many member functions impose stricter requirements.
.. erasable is:
the type t erasable container x if, given
a
allocator type definedx::allocator_type
m
lvalue of typea
obtainedx::get_allocator()
p
pointer of typet*
prepared containerthe following expression well-formed:
std::allocator_traits<a>::destroy(m, p);
and @ "type requirements" of std::vector::resize() reference:
t must meet requirements of moveinsertable , defaultinsertable in order use overload (1).
so t doesn't need copyable - needs destroyable, movable , default construct-able.
moreover, since c++14, restriction of complete type removed.
the requirements imposed on elements depend on actual operations performed on container. generally, required element type meets requirements of erasable, many member functions impose stricter requirements. this container (but not members) can instantiated incomplete element type if allocator satisfies allocator completeness requirements.
therefore, think it's because of poor standard-conforming of vs2012. has defect on latest c++ (e.g. noexcept
)
c++11 standard paper n3337 says
void resize(size_type sz);
effects: if
sz <= size()
, equivalenterase(begin() + sz, end());
. ifsize() < sz
, appendssz - size()
value-initialized elements sequence.requires: t shall copyinsertable *this.
therefore in strict c++11, cannot use std::vector::resize()
in case. (you can use std::vector
, though)
however, it standard defect , fixed in c++14. , guess many compilers work non-copyable types because copying isn't need implementing std::vector::resize()
indeed. although vs2012 doesn't work, it's because bug of vs2012 @comicsansms answered, not because of std::vector::resize()
itself.
Comments
Post a Comment