| // { dg-do run { target c++11 } } |
| |
| // The class X and test code is by by Howard Hinnant and used under a |
| // Creative Commons Attribution 4.0 International License. |
| // http://creativecommons.org/licenses/by/4.0/ |
| // https://github.com/HowardHinnant/papers/blob/master/insert_vs_emplace.html |
| // |
| // The original code was reformatted and modified to use the VERIFY macro |
| // instead of writing to standard output. |
| |
| #include <testsuite_hooks.h> |
| #include <vector> |
| #include <iostream> |
| |
| class X |
| { |
| int i_; |
| int* p_; |
| |
| public: |
| struct special |
| { |
| unsigned c; |
| unsigned dt; |
| unsigned cc; |
| unsigned ca; |
| unsigned mc; |
| unsigned 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=(const X& x) |
| { |
| |
| i_ = x.i_; |
| p_ = x.p_; |
| // std::cout << "X& operator=(const X& x)\n"; |
| sp.ca++; |
| return *this; |
| } |
| |
| X(X&& x) noexcept |
| : i_(x.i_) |
| , p_(x.p_) |
| { |
| // std::cout << "X(X&& x)\n"; |
| sp.mc++; |
| } |
| |
| X& operator=(X&& x) noexcept |
| { |
| |
| 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 << sp.c << '\n'; |
| os << sp.dt << '\n'; |
| os << sp.cc << '\n'; |
| os << sp.ca << '\n'; |
| os << sp.mc << '\n'; |
| os << sp.ma << '\n'; |
| return os; |
| } |
| |
| X::special X::sp{}; |
| |
| bool |
| operator==(const X::special& lhs, const X::special& rhs) |
| { |
| return lhs.c == rhs.c && lhs.dt == rhs.dt |
| && lhs.cc == rhs.cc && lhs.ca == rhs.ca |
| && lhs.mc == rhs.mc && lhs.ma == rhs.ma; |
| } |
| |
| // Verify that insert and emplace are equally efficient. |
| // Also verify exact number of operations (which are specific to this |
| // implementation) in order to catch any regressions. |
| |
| // insert vs emplace lvalue no reallocation |
| void |
| test01() |
| { |
| const X::special expected{ 0, 1, 1, 0, 1, 3 }; |
| X::special ins, emp; |
| { |
| std::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 = {}; |
| v.insert(v.begin(), x); |
| // std::cout << X::sp; |
| // std::cout << "----\n"; |
| ins = X::sp; |
| } |
| { |
| std::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 = {}; |
| v.emplace(v.begin(), x); |
| // std::cout << X::sp; |
| // std::cout << "----\n"; |
| emp = X::sp; |
| } |
| VERIFY( ins == emp ); |
| VERIFY( ins == expected ); |
| } |
| |
| // insert vs emplace xvalue no reallocation |
| void |
| test02() |
| { |
| const X::special expected{ 0, 0, 0, 0, 1, 3 }; |
| X::special ins, emp; |
| { |
| std::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 = {}; |
| v.insert(v.begin(), std::move(x)); |
| // std::cout << X::sp; |
| // std::cout << "----\n"; |
| ins = X::sp; |
| } |
| { |
| std::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 = {}; |
| v.emplace(v.begin(), std::move(x)); |
| // std::cout << X::sp; |
| // std::cout << "----\n"; |
| emp = X::sp; |
| } |
| VERIFY( ins == emp ); |
| VERIFY( ins == expected ); |
| } |
| |
| // insert vs emplace rvalue no reallocation |
| void |
| test03() |
| { |
| const X::special expected{ 1, 1, 0, 0, 1, 3 }; |
| X::special ins, emp; |
| { |
| std::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 = {}; |
| v.insert(v.begin(), X{0,0}); |
| // std::cout << X::sp; |
| // std::cout << "----\n"; |
| ins = X::sp; |
| } |
| { |
| std::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 = {}; |
| v.emplace(v.begin(), X{0,0}); |
| // std::cout << X::sp; |
| // std::cout << "----\n"; |
| emp = X::sp; |
| } |
| VERIFY( ins == emp ); |
| VERIFY( ins == expected ); |
| } |
| |
| // insert vs emplace lvalue reallocation |
| void |
| test04() |
| { |
| const X::special expected{ 0, 3, 1, 0, 3, 0 }; |
| X::special ins, emp; |
| { |
| std::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 = {}; |
| v.insert(v.begin(), x); |
| // std::cout << X::sp; |
| // std::cout << "----\n"; |
| ins = X::sp; |
| } |
| { |
| std::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 = {}; |
| v.emplace(v.begin(), x); |
| // std::cout << X::sp; |
| // std::cout << "----\n"; |
| emp = X::sp; |
| } |
| VERIFY( ins == emp ); |
| VERIFY( ins == expected ); |
| } |
| |
| // insert vs emplace xvalue reallocation |
| void |
| test05() |
| { |
| const X::special expected{ 0, 3, 0, 0, 4, 0 }; |
| X::special ins, emp; |
| { |
| std::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 = {}; |
| v.insert(v.begin(), std::move(x)); |
| // std::cout << X::sp; |
| // std::cout << "----\n"; |
| ins = X::sp; |
| } |
| { |
| std::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 = {}; |
| v.emplace(v.begin(), std::move(x)); |
| // std::cout << X::sp; |
| // std::cout << "----\n"; |
| emp = X::sp; |
| } |
| VERIFY( ins == emp ); |
| VERIFY( ins == expected ); |
| } |
| |
| // insert vs emplace rvalue reallocation |
| void |
| test06() |
| { |
| const X::special expected{ 1, 4, 0, 0, 4, 0 }; |
| X::special ins, emp; |
| { |
| std::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 = {}; |
| v.insert(v.begin(), X{0,0}); |
| // std::cout << X::sp; |
| // std::cout << "----\n"; |
| ins = X::sp; |
| } |
| { |
| std::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 = {}; |
| v.emplace(v.begin(), X{0,0}); |
| // std::cout << X::sp; |
| // std::cout << "----\n"; |
| emp = X::sp; |
| } |
| VERIFY( ins == emp ); |
| VERIFY( ins == expected ); |
| } |
| |
| // push_back vs emplace_back lvalue no reallocation |
| void |
| test07() |
| { |
| const X::special expected{ 0, 0, 1, 0, 0, 0 }; |
| X::special ins, emp; |
| { |
| std::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 = {}; |
| v.push_back(x); |
| // std::cout << X::sp; |
| // std::cout << "----\n"; |
| ins = X::sp; |
| } |
| { |
| std::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 = {}; |
| v.emplace_back(x); |
| // std::cout << X::sp; |
| // std::cout << "----\n"; |
| emp = X::sp; |
| } |
| VERIFY( ins == emp ); |
| VERIFY( ins == expected ); |
| } |
| |
| // push_back vs emplace_back xvalue no reallocation |
| void |
| test08() |
| { |
| const X::special expected{ 0, 0, 0, 0, 1, 0 }; |
| X::special ins, emp; |
| { |
| std::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 = {}; |
| v.push_back(std::move(x)); |
| // std::cout << X::sp; |
| // std::cout << "----\n"; |
| ins = X::sp; |
| } |
| { |
| std::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 = {}; |
| v.emplace_back(std::move(x)); |
| // std::cout << X::sp; |
| // std::cout << "----\n"; |
| emp = X::sp; |
| } |
| VERIFY( ins == emp ); |
| VERIFY( ins == expected ); |
| } |
| |
| // push_back vs emplace_back rvalue no reallocation |
| void |
| test09() |
| { |
| const X::special expected{ 1, 1, 0, 0, 1, 0 }; |
| X::special ins, emp; |
| { |
| std::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 = {}; |
| v.push_back(X{0,0}); |
| // std::cout << X::sp; |
| // std::cout << "----\n"; |
| ins = X::sp; |
| } |
| { |
| std::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 = {}; |
| v.emplace_back(X{0,0}); |
| // std::cout << X::sp; |
| // std::cout << "----\n"; |
| emp = X::sp; |
| } |
| VERIFY( ins == emp ); |
| VERIFY( ins == expected ); |
| } |
| |
| // push_back vs emplace_back lvalue reallocation |
| void |
| test10() |
| { |
| const X::special expected{ 0, 3, 1, 0, 3, 0 }; |
| X::special ins, emp; |
| { |
| std::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 = {}; |
| v.push_back(x); |
| // std::cout << X::sp; |
| // std::cout << "----\n"; |
| ins = X::sp; |
| } |
| { |
| std::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 = {}; |
| v.emplace_back(x); |
| // std::cout << X::sp; |
| // std::cout << "----\n"; |
| emp = X::sp; |
| } |
| VERIFY( ins == emp ); |
| VERIFY( ins == expected ); |
| } |
| |
| // push_back vs emplace_back xvalue reallocation |
| void |
| test11() |
| { |
| const X::special expected{ 0, 3, 0, 0, 4, 0 }; |
| X::special ins, emp; |
| { |
| std::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 = {}; |
| v.push_back(std::move(x)); |
| // std::cout << X::sp; |
| // std::cout << "----\n"; |
| ins = X::sp; |
| } |
| { |
| std::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 = {}; |
| v.emplace_back(std::move(x)); |
| // std::cout << X::sp; |
| // std::cout << "----\n"; |
| emp = X::sp; |
| } |
| VERIFY( ins == emp ); |
| VERIFY( ins == expected ); |
| } |
| |
| // push_back vs emplace_back rvalue reallocation |
| void |
| test12() |
| { |
| const X::special expected{ 1, 4, 0, 0, 4, 0 }; |
| X::special ins, emp; |
| { |
| std::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 = {}; |
| v.push_back(X{0,0}); |
| // std::cout << X::sp; |
| // std::cout << "----\n"; |
| ins = X::sp; |
| } |
| { |
| std::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 = {}; |
| v.emplace_back(X{0,0}); |
| // std::cout << X::sp; |
| // std::cout << "----\n"; |
| emp = X::sp; |
| } |
| VERIFY( ins == emp ); |
| VERIFY( ins == expected ); |
| } |
| |
| int |
| main() |
| { |
| test01(); |
| test02(); |
| test03(); |
| test04(); |
| test05(); |
| test06(); |
| test07(); |
| test08(); |
| test09(); |
| test10(); |
| test11(); |
| test12(); |
| } |