Home | History | Annotate | Download | only in unord.map.modifiers
      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 M>
     17 //  pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);            // C++17
     18 // template <class M>
     19 //  pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj);                 // C++17
     20 // template <class M>
     21 //  iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj);   // C++17
     22 // template <class M>
     23 //  iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);        // C++17
     24 
     25 #include <unordered_map>
     26 #include <cassert>
     27 #include <tuple>
     28 
     29 
     30 class Moveable
     31 {
     32     Moveable(const Moveable&);
     33     Moveable& operator=(const Moveable&);
     34 
     35     int int_;
     36     double double_;
     37 public:
     38     Moveable() : int_(0), double_(0) {}
     39     Moveable(int i, double d) : int_(i), double_(d) {}
     40     Moveable(Moveable&& x)
     41         : int_(x.int_), double_(x.double_)
     42             {x.int_ = -1; x.double_ = -1;}
     43     Moveable& operator=(Moveable&& x)
     44         {int_ = x.int_; x.int_ = -1;
     45          double_ = x.double_; x.double_ = -1;
     46          return *this;
     47         }
     48 
     49     bool operator==(const Moveable& x) const
     50         {return int_ == x.int_ && double_ == x.double_;}
     51     bool operator<(const Moveable& x) const
     52         {return int_ < x.int_ || (int_ == x.int_ && double_ < x.double_);}
     53     size_t hash () const { return std::hash<int>()(int_) + std::hash<double>()(double_); }
     54 
     55     int get() const {return int_;}
     56     bool moved() const {return int_ == -1;}
     57 };
     58 
     59 namespace std {
     60     template <> struct hash<Moveable> {
     61         size_t operator () (const Moveable &m) const { return m.hash(); }
     62     };
     63 }
     64 
     65 int main()
     66 {
     67 
     68     { // pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);
     69         typedef std::unordered_map<int, Moveable> M;
     70         typedef std::pair<M::iterator, bool> R;
     71         M m;
     72         R r;
     73         for (int i = 0; i < 20; i += 2)
     74             m.emplace ( i, Moveable(i, (double) i));
     75         assert(m.size() == 10);
     76 
     77         for (int i=0; i < 20; i += 2)
     78         {
     79             Moveable mv(i+1, i+1);
     80             r = m.insert_or_assign(i, std::move(mv));
     81             assert(m.size() == 10);
     82             assert(!r.second);                    // was not inserted
     83             assert(mv.moved());                   // was moved from
     84             assert(r.first->first == i);          // key
     85             assert(r.first->second.get() == i+1); // value
     86         }
     87 
     88         Moveable mv1(5, 5.0);
     89         r = m.insert_or_assign(-1, std::move(mv1));
     90         assert(m.size() == 11);
     91         assert(r.second);                    // was inserted
     92         assert(mv1.moved());                 // was moved from
     93         assert(r.first->first        == -1); // key
     94         assert(r.first->second.get() == 5);  // value
     95 
     96         Moveable mv2(9, 9.0);
     97         r = m.insert_or_assign(3, std::move(mv2));
     98         assert(m.size() == 12);
     99         assert(r.second);                   // was inserted
    100         assert(mv2.moved());                // was moved from
    101         assert(r.first->first        == 3); // key
    102         assert(r.first->second.get() == 9); // value
    103 
    104         Moveable mv3(-1, 5.0);
    105         r = m.insert_or_assign(117, std::move(mv3));
    106         assert(m.size() == 13);
    107         assert(r.second);                     // was inserted
    108         assert(mv3.moved());                  // was moved from
    109         assert(r.first->first        == 117); // key
    110         assert(r.first->second.get() == -1);  // value
    111     }
    112     { // pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj);
    113         typedef std::unordered_map<Moveable, Moveable> M;
    114         typedef std::pair<M::iterator, bool> R;
    115         M m;
    116         R r;
    117         for (int i = 0; i < 20; i += 2)
    118             m.emplace ( Moveable(i, (double) i), Moveable(i+1, (double) i+1));
    119         assert(m.size() == 10);
    120 
    121         Moveable mvkey1(2, 2.0);
    122         Moveable mv1(4, 4.0);
    123         r = m.insert_or_assign(std::move(mvkey1), std::move(mv1));
    124         assert(m.size() == 10);
    125         assert(!r.second);                  // was not inserted
    126         assert(!mvkey1.moved());            // was not moved from
    127         assert(mv1.moved());                // was moved from
    128         assert(r.first->first == mvkey1);   // key
    129         assert(r.first->second.get() == 4); // value
    130 
    131         Moveable mvkey2(3, 3.0);
    132         Moveable mv2(5, 5.0);
    133         r = m.try_emplace(std::move(mvkey2), std::move(mv2));
    134         assert(m.size() == 11);
    135         assert(r.second);                   // was inserted
    136         assert(mv2.moved());                // was moved from
    137         assert(mvkey2.moved());             // was moved from
    138         assert(r.first->first.get()  == 3); // key
    139         assert(r.first->second.get() == 5); // value
    140     }
    141     { // iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj);
    142         typedef std::unordered_map<int, Moveable> M;
    143         M m;
    144         M::iterator r;
    145         for (int i = 0; i < 20; i += 2)
    146             m.emplace ( i, Moveable(i, (double) i));
    147         assert(m.size() == 10);
    148         M::const_iterator it = m.find(2);
    149 
    150         Moveable mv1(3, 3.0);
    151         r = m.insert_or_assign(it, 2, std::move(mv1));
    152         assert(m.size() == 10);
    153         assert(mv1.moved());           // was moved from
    154         assert(r->first        == 2);  // key
    155         assert(r->second.get() == 3);  // value
    156 
    157         Moveable mv2(5, 5.0);
    158         r = m.insert_or_assign(it, 3, std::move(mv2));
    159         assert(m.size() == 11);
    160         assert(mv2.moved());           // was moved from
    161         assert(r->first        == 3);  // key
    162         assert(r->second.get() == 5);  // value
    163     }
    164     { // iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);
    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.insert_or_assign(it, std::move(mvkey1), std::move(mv1));
    176         assert(m.size() == 10);
    177         assert(mv1.moved());          // was moved from
    178         assert(!mvkey1.moved());      // was not moved from
    179         assert(r->first == mvkey1);   // key
    180         assert(r->second.get() == 4); // value
    181 
    182         Moveable mvkey2(3, 3.0);
    183         Moveable mv2(5, 5.0);
    184         r = m.insert_or_assign(it, std::move(mvkey2), std::move(mv2));
    185         assert(m.size() == 11);
    186         assert(mv2.moved());           // was moved from
    187         assert(mvkey2.moved());        // was moved from
    188         assert(r->first.get()  == 3);  // key
    189         assert(r->second.get() == 5);  // value
    190     }
    191 
    192 }