libcxx

libcxx mirror with random patches
git clone https://git.neptards.moe/neptards/libcxx.git
Log | Files | Refs

try.emplace.pass.cpp (6869B)


      1 //===----------------------------------------------------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is dual licensed under the MIT and the University of Illinois Open
      6 // Source Licenses. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // UNSUPPORTED: c++98, c++03, c++11, c++14
     11 
     12 // <unordered_map>
     13 
     14 // class unordered_map
     15 
     16 // template <class... Args>
     17 //  pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);          // C++17
     18 // template <class... Args>
     19 //  pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);               // C++17
     20 // template <class... Args>
     21 //  iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); // C++17
     22 // template <class... Args>
     23 //  iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);      // C++17
     24 
     25 #include <unordered_map>
     26 #include <cassert>
     27 #include <tuple>
     28 
     29 class Moveable
     30 {
     31     Moveable(const Moveable&);
     32     Moveable& operator=(const Moveable&);
     33 
     34     int int_;
     35     double double_;
     36 public:
     37     Moveable() : int_(0), double_(0) {}
     38     Moveable(int i, double d) : int_(i), double_(d) {}
     39     Moveable(Moveable&& x)
     40         : int_(x.int_), double_(x.double_)
     41             {x.int_ = -1; x.double_ = -1;}
     42     Moveable& operator=(Moveable&& x)
     43         {int_ = x.int_; x.int_ = -1;
     44          double_ = x.double_; x.double_ = -1;
     45          return *this;
     46         }
     47 
     48     bool operator==(const Moveable& x) const
     49         {return int_ == x.int_ && double_ == x.double_;}
     50     bool operator<(const Moveable& x) const
     51         {return int_ < x.int_ || (int_ == x.int_ && double_ < x.double_);}
     52     size_t hash () const { return std::hash<int>()(int_) + std::hash<double>()(double_); }
     53 
     54     int get() const {return int_;}
     55     bool moved() const {return int_ == -1;}
     56 };
     57 
     58 namespace std {
     59     template <> struct hash<Moveable> {
     60         size_t operator () (const Moveable &m) const { return m.hash(); }
     61     };
     62 }
     63 
     64 int main()
     65 {
     66 
     67     { // pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
     68         typedef std::unordered_map<int, Moveable> M;
     69         typedef std::pair<M::iterator, bool> R;
     70         M m;
     71         R r;
     72         for (int i = 0; i < 20; i += 2)
     73             m.emplace (i, Moveable(i, (double) i));
     74         assert(m.size() == 10);
     75 
     76         Moveable mv1(3, 3.0);
     77         for (int i=0; i < 20; i += 2)
     78         {
     79             r = m.try_emplace(i, std::move(mv1));
     80             assert(m.size() == 10);
     81             assert(!r.second);              // was not inserted
     82             assert(!mv1.moved());           // was not moved from
     83             assert(r.first->first == i);    // key
     84         }
     85 
     86         r = m.try_emplace(-1, std::move(mv1));
     87         assert(m.size() == 11);
     88         assert(r.second);                   // was inserted
     89         assert(mv1.moved());                // was moved from
     90         assert(r.first->first == -1);       // key
     91         assert(r.first->second.get() == 3); // value
     92 
     93         Moveable mv2(5, 3.0);
     94         r = m.try_emplace(5, std::move(mv2));
     95         assert(m.size() == 12);
     96         assert(r.second);                   // was inserted
     97         assert(mv2.moved());                // was moved from
     98         assert(r.first->first == 5);        // key
     99         assert(r.first->second.get() == 5); // value
    100 
    101         Moveable mv3(-1, 3.0);
    102         r = m.try_emplace(117, std::move(mv2));
    103         assert(m.size() == 13);
    104         assert(r.second);                    // was inserted
    105         assert(mv2.moved());                 // was moved from
    106         assert(r.first->first == 117);       // key
    107         assert(r.first->second.get() == -1); // value
    108     }
    109 
    110     {  // pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);
    111         typedef std::unordered_map<Moveable, Moveable> M;
    112         typedef std::pair<M::iterator, bool> R;
    113         M m;
    114         R r;
    115         for (int i = 0; i < 20; i += 2)
    116             m.emplace ( Moveable(i, (double) i), Moveable(i+1, (double) i+1));
    117         assert(m.size() == 10);
    118 
    119         Moveable mvkey1(2, 2.0);
    120         Moveable mv1(4, 4.0);
    121         r = m.try_emplace(std::move(mvkey1), std::move(mv1));
    122         assert(m.size() == 10);
    123         assert(!r.second);                 // was not inserted
    124         assert(!mv1.moved());              // was not moved from
    125         assert(!mvkey1.moved());           // was not moved from
    126         assert(r.first->first == mvkey1);  // key
    127 
    128         Moveable mvkey2(3, 3.0);
    129         r = m.try_emplace(std::move(mvkey2), std::move(mv1));
    130         assert(m.size() == 11);
    131         assert(r.second);                   // was inserted
    132         assert(mv1.moved());                // was moved from
    133         assert(mvkey2.moved());             // was moved from
    134         assert(r.first->first.get()  == 3); // key
    135         assert(r.first->second.get() == 4); // value
    136     }
    137 
    138     {  // iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args);
    139         typedef std::unordered_map<int, Moveable> M;
    140         M m;
    141         M::iterator r;
    142         for (int i = 0; i < 20; i += 2)
    143             m.try_emplace ( i, Moveable(i, (double) i));
    144         assert(m.size() == 10);
    145         M::const_iterator it = m.find(2);
    146 
    147         Moveable mv1(3, 3.0);
    148         for (int i=0; i < 20; i += 2)
    149         {
    150             r = m.try_emplace(it, i, std::move(mv1));
    151             assert(m.size() == 10);
    152             assert(!mv1.moved());         // was not moved from
    153             assert(r->first == i);        // key
    154             assert(r->second.get() == i); // value
    155         }
    156 
    157         r = m.try_emplace(it, 3, std::move(mv1));
    158         assert(m.size() == 11);
    159         assert(mv1.moved());          // was moved from
    160         assert(r->first == 3);        // key
    161         assert(r->second.get() == 3); // value
    162     }
    163 
    164     {  // iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);
    165         typedef std::unordered_map<Moveable, Moveable> M;
    166         M m;
    167         M::iterator r;
    168         for ( int i = 0; i < 20; i += 2 )
    169             m.emplace ( Moveable(i, (double) i), Moveable(i+1, (double) i+1));
    170         assert(m.size() == 10);
    171         M::const_iterator it = std::next(m.cbegin());
    172 
    173         Moveable mvkey1(2, 2.0);
    174         Moveable mv1(4, 4.0);
    175         r = m.try_emplace(it, std::move(mvkey1), std::move(mv1));
    176         assert(m.size() == 10);
    177         assert(!mv1.moved());        // was not moved from
    178         assert(!mvkey1.moved());     // was not moved from
    179         assert(r->first == mvkey1);  // key
    180 
    181         Moveable mvkey2(3, 3.0);
    182         r = m.try_emplace(it, std::move(mvkey2), std::move(mv1));
    183         assert(m.size() == 11);
    184         assert(mv1.moved());          // was moved from
    185         assert(mvkey2.moved());       // was moved from
    186         assert(r->first.get()  == 3); // key
    187         assert(r->second.get() == 4); // value
    188     }
    189 }