123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498 |
- //////////////////////////////////////////////////////////////////////////////
- //
- // (C) Copyright Howard Hinnant 2014.
- // (C) Copyright Ion Gaztanaga 2014-2014. Distributed under the Boost
- // Software License, Version 1.0. (See accompanying file
- // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- //
- // See http://www.boost.org/libs/container for documentation.
- //
- //////////////////////////////////////////////////////////////////////////////
- //
- // This testcase is based on H. Hinnant's article "Insert vs. Emplace",
- // (http://github.com/HowardHinnant/papers/blob/master/insert_vs_emplace.html)
- //
- //////////////////////////////////////////////////////////////////////////////
- #include <iostream>
- #include <boost/move/utility_core.hpp>
- #include <boost/container/vector.hpp>
- #include <boost/core/lightweight_test.hpp>
- class X
- {
- int i_;
- int* p_;
- BOOST_COPYABLE_AND_MOVABLE(X)
- public:
- struct special
- {
- unsigned c;
- unsigned dt;
- unsigned cc;
- unsigned ca;
- unsigned mc;
- unsigned ma;
- friend bool operator==(const special &l, const special &r)
- { return l.c == r.c && l.dt == r.dt && l.cc == r.cc && l.ca == r.ca && l.mc == r.mc && l.ma == r.ma; }
- };
- static special sp;
- X(int i, int* p)
- : i_(i)
- , p_(p)
- {
- // std::cout << "X(int i, int* p)\n";
- sp.c++;
- }
- ~X()
- {
- // std::cout << "~X()\n";
- sp.dt++;
- }
- X(const X& x)
- : i_(x.i_)
- , p_(x.p_)
- {
- // std::cout << "X(const X& x)\n";
- sp.cc++;
- }
- X& operator=(BOOST_COPY_ASSIGN_REF(X) x)
- {
- i_ = x.i_;
- p_ = x.p_;
- // std::cout << "X& operator=(const X& x)\n";
- sp.ca++;
- return *this;
- }
- X(BOOST_RV_REF(X) x) BOOST_NOEXCEPT_OR_NOTHROW
- : i_(x.i_)
- , p_(x.p_)
- {
- // std::cout << "X(X&& x)\n";
- sp.mc++;
- }
- X& operator=(BOOST_RV_REF(X) x) BOOST_NOEXCEPT_OR_NOTHROW
- {
- i_ = x.i_;
- p_ = x.p_;
- // std::cout << "X& operator=(X&& x)\n";
- sp.ma++;
- return *this;
- }
- };
- std::ostream&
- operator<<(std::ostream& os, X::special const& sp)
- {
- os << "Const: " << sp.c << '\n';
- os << "Destr: " << sp.dt << '\n';
- os << "CopyC: " << sp.cc << '\n';
- os << "CopyA: " << sp.ca << '\n';
- os << "MoveC: " << sp.mc << '\n';
- os << "MoveA: " << sp.ma << '\n';
- os << "Total: " << (sp.c + sp.dt + sp.cc + sp.ca + sp.mc + sp.ma) << '\n';
- return os;
- }
- X::special X::sp = X::special();
- const X produce_const_prvalue()
- { return X(0, 0); }
- int main()
- {
- X::special insert_results;
- X::special emplace_results;
- {
- boost::container::vector<X> v;
- v.reserve(4);
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- X x(0,0);
- std::cout << "--insert lvalue no reallocation--\n";
- X::sp = X::special();
- v.insert(v.begin(), x);
- std::cout << X::sp;
- std::cout << "----\n";
- insert_results = X::sp;
- }
- {
- boost::container::vector<X> v;
- v.reserve(4);
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- X x(0,0);
- std::cout << "--emplace lvalue no reallocation--\n";
- X::sp = X::special();
- v.emplace(v.begin(), x);
- std::cout << X::sp;
- std::cout << "----\n";
- emplace_results = X::sp;
- }
- {
- boost::container::vector<X> v;
- v.reserve(4);
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- X x(0,0);
- std::cout << "--insert xvalue no reallocation--\n";
- X::sp = X::special();
- v.insert(v.begin(), boost::move(x));
- std::cout << X::sp;
- std::cout << "----\n";
- insert_results = X::sp;
- }
- {
- boost::container::vector<X> v;
- v.reserve(4);
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- X x(0,0);
- std::cout << "--emplace xvalue no reallocation--\n";
- X::sp = X::special();
- v.emplace(v.begin(), boost::move(x));
- std::cout << X::sp;
- std::cout << "----\n";
- emplace_results = X::sp;
- }
- BOOST_TEST_EQ(insert_results == emplace_results, true);
- {
- boost::container::vector<X> v;
- v.reserve(4);
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- X x(0,0);
- std::cout << "--emplace const prvalue no reallocation--\n";
- X::sp = X::special();
- v.emplace(v.begin(), produce_const_prvalue());
- std::cout << X::sp;
- std::cout << "----\n";
- emplace_results = X::sp;
- }
- {
- boost::container::vector<X> v;
- v.reserve(4);
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- X x(0,0);
- std::cout << "--emplace const prvalue no reallocation--\n";
- X::sp = X::special();
- v.insert(v.begin(), produce_const_prvalue());
- std::cout << X::sp;
- std::cout << "----\n";
- insert_results = X::sp;
- }
- BOOST_TEST_EQ(insert_results == emplace_results, true);
- {
- boost::container::vector<X> v;
- v.reserve(4);
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- std::cout << "--insert rvalue no reallocation--\n";
- X::sp = X::special();
- v.insert(v.begin(), X(0,0));
- std::cout << X::sp;
- std::cout << "----\n";
- insert_results = X::sp;
- }
- {
- boost::container::vector<X> v;
- v.reserve(4);
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- std::cout << "--emplace rvalue no reallocation--\n";
- X::sp = X::special();
- v.emplace(v.begin(), X(0,0));
- std::cout << X::sp;
- std::cout << "----\n";
- emplace_results = X::sp;
- }
- //With emulated move semantics an extra copy is unavoidable
- #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
- BOOST_TEST_EQ(insert_results == emplace_results, true);
- #endif
- {
- boost::container::vector<X> v;
- v.reserve(3);
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- X x(0,0);
- std::cout << "--insert lvalue reallocation--\n";
- X::sp = X::special();
- v.insert(v.begin(), x);
- std::cout << X::sp;
- std::cout << "----\n";
- insert_results = X::sp;
- }
- {
- boost::container::vector<X> v;
- v.reserve(3);
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- X x(0,0);
- std::cout << "--emplace lvalue reallocation--\n";
- X::sp = X::special();
- v.emplace(v.begin(), x);
- std::cout << X::sp;
- std::cout << "----\n";
- emplace_results = X::sp;
- }
- BOOST_TEST_EQ(insert_results == emplace_results, true);
- {
- boost::container::vector<X> v;
- v.reserve(3);
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- X x(0,0);
- std::cout << "--insert xvalue reallocation--\n";
- X::sp = X::special();
- v.insert(v.begin(), boost::move(x));
- std::cout << X::sp;
- std::cout << "----\n";
- insert_results = X::sp;
- }
- {
- boost::container::vector<X> v;
- v.reserve(3);
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- X x(0,0);
- std::cout << "--emplace xvalue reallocation--\n";
- X::sp = X::special();
- v.emplace(v.begin(), boost::move(x));
- std::cout << X::sp;
- std::cout << "----\n";
- emplace_results = X::sp;
- }
- BOOST_TEST_EQ(insert_results == emplace_results, true);
- {
- boost::container::vector<X> v;
- v.reserve(3);
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- std::cout << "--insert rvalue reallocation--\n";
- X::sp = X::special();
- v.insert(v.begin(), X(0,0));
- std::cout << X::sp;
- std::cout << "----\n";
- insert_results = X::sp;
- }
- {
- boost::container::vector<X> v;
- v.reserve(3);
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- std::cout << "--emplace rvalue reallocation--\n";
- X::sp = X::special();
- v.emplace(v.begin(), X(0,0));
- std::cout << X::sp;
- std::cout << "----\n";
- emplace_results = X::sp;
- }
- //With emulated move semantics an extra copy is unavoidable
- #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
- BOOST_TEST_EQ(insert_results == emplace_results, true);
- #endif
- {
- boost::container::vector<X> v;
- v.reserve(4);
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- X x(0,0);
- std::cout << "--push_back lvalue no reallocation--\n";
- X::sp = X::special();
- v.push_back(x);
- std::cout << X::sp;
- std::cout << "----\n";
- insert_results = X::sp;
- }
- {
- boost::container::vector<X> v;
- v.reserve(4);
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- X x(0,0);
- std::cout << "--emplace_back lvalue no reallocation--\n";
- X::sp = X::special();
- v.emplace_back(x);
- std::cout << X::sp;
- std::cout << "----\n";
- emplace_results = X::sp;
- }
- BOOST_TEST_EQ(insert_results == emplace_results, true);
- {
- boost::container::vector<X> v;
- v.reserve(4);
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- X x(0,0);
- std::cout << "--push_back xvalue no reallocation--\n";
- X::sp = X::special();
- v.push_back(boost::move(x));
- std::cout << X::sp;
- std::cout << "----\n";
- insert_results = X::sp;
- }
- {
- boost::container::vector<X> v;
- v.reserve(4);
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- X x(0,0);
- std::cout << "--emplace_back xvalue no reallocation--\n";
- X::sp = X::special();
- v.emplace_back(boost::move(x));
- std::cout << X::sp;
- std::cout << "----\n";
- emplace_results = X::sp;
- }
- BOOST_TEST_EQ(insert_results == emplace_results, true);
- {
- boost::container::vector<X> v;
- v.reserve(4);
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- std::cout << "--push_back rvalue no reallocation--\n";
- X::sp = X::special();
- v.push_back(X(0,0));
- std::cout << X::sp;
- std::cout << "----\n";
- insert_results = X::sp;
- }
- {
- boost::container::vector<X> v;
- v.reserve(4);
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- std::cout << "--emplace_back rvalue no reallocation--\n";
- X::sp = X::special();
- v.emplace_back(X(0,0));
- std::cout << X::sp;
- std::cout << "----\n";
- emplace_results = X::sp;
- }
- //With emulated move semantics an extra copy is unavoidable
- #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
- BOOST_TEST_EQ(insert_results == emplace_results, true);
- #endif
- {
- boost::container::vector<X> v;
- v.reserve(3);
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- X x(0,0);
- std::cout << "--push_back lvalue reallocation--\n";
- X::sp = X::special();
- v.push_back(x);
- std::cout << X::sp;
- std::cout << "----\n";
- insert_results = X::sp;
- }
- {
- boost::container::vector<X> v;
- v.reserve(3);
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- X x(0,0);
- std::cout << "--emplace_back lvalue reallocation--\n";
- X::sp = X::special();
- v.emplace_back(x);
- std::cout << X::sp;
- std::cout << "----\n";
- emplace_results = X::sp;
- }
- BOOST_TEST_EQ(insert_results == emplace_results, true);
- {
- boost::container::vector<X> v;
- v.reserve(3);
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- X x(0,0);
- std::cout << "--push_back xvalue reallocation--\n";
- X::sp = X::special();
- v.push_back(boost::move(x));
- std::cout << X::sp;
- std::cout << "----\n";
- insert_results = X::sp;
- }
- {
- boost::container::vector<X> v;
- v.reserve(3);
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- X x(0,0);
- std::cout << "--emplace_back xvalue reallocation--\n";
- X::sp = X::special();
- v.emplace_back(boost::move(x));
- std::cout << X::sp;
- std::cout << "----\n";
- emplace_results = X::sp;
- }
- BOOST_TEST_EQ(insert_results == emplace_results, true);
- {
- boost::container::vector<X> v;
- v.reserve(3);
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- std::cout << "--push_back rvalue reallocation--\n";
- X::sp = X::special();
- v.push_back(X(0,0));
- std::cout << X::sp;
- std::cout << "----\n";
- insert_results = X::sp;
- }
- {
- boost::container::vector<X> v;
- v.reserve(3);
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- v.push_back(X(0,0));
- std::cout << "--emplace_back rvalue reallocation--\n";
- X::sp = X::special();
- v.emplace_back(X(0,0));
- std::cout << X::sp;
- std::cout << "----\n";
- emplace_results = X::sp;
- }
- //With emulated move semantics an extra copy is unavoidable
- #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
- BOOST_TEST_EQ(insert_results == emplace_results, true);
- #endif
- return boost::report_errors();
- }
|