blob: ccdc08f746132b382e1259e1ad78f6f1dee19b42 [file] [log] [blame]
// { dg-do run { target c++17 } }
// Copyright (C) 2015-2022 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#include <utility>
#include <unordered_map>
#include <testsuite_hooks.h>
struct Val
{
bool moved_from_ctor = false;
bool moved_from_assign = false;
int val;
Val(int val = 0) : val(val) {}
Val(const Val& other) : val(other.val)
{
}
Val(Val&& other) : val(other.val)
{
other.moved_from_ctor = true;
}
Val& operator=(Val&& other)
{
val = other.val;
other.moved_from_assign = true;
return *this;
}
Val& operator=(const Val& other)
{
val = other.val;
return *this;
}
};
bool operator==(const Val& a, const Val& b)
{
return a.val == b.val;
}
namespace std
{
template <> struct hash<Val>
{
using result_type = size_t;
using argument_type = Val;
size_t
operator()(const Val& t) const
noexcept
{
return hash<int>{}(t.val);
}
};
}
void test01()
{
typedef std::unordered_map<int, Val> Map;
Map m;
auto res1 = m.insert_or_assign(0, Val(5));
VERIFY(res1.second);
VERIFY(res1.first != m.end());
VERIFY(m[0].val == 5);
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.insert_or_assign(0, std::move(v1));
VERIFY(!res2.second);
VERIFY(res2.first == res1.first);
VERIFY(m[0].val == 6);
VERIFY(!v1.moved_from_ctor);
VERIFY(v1.moved_from_assign);
VERIFY(m.size() == 1);
v1.moved_from_assign = false;
auto res3 = m.insert_or_assign(1, std::move(v1));
VERIFY(res3.first != res1.first && res3.first != m.end());
VERIFY(res3.second);
VERIFY(m[0].val == 6);
VERIFY(m[1].val == 6);
VERIFY(v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
void test02()
{
typedef std::unordered_map<int, Val> Map;
Map m;
auto res1 = m.insert_or_assign(m.begin(), 0, Val(5));
VERIFY(res1 != m.end());
VERIFY(m[0].val == 5);
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.insert_or_assign(m.begin(), 0, std::move(v1));
VERIFY(res2 == res1);
VERIFY(m[0].val == 6);
VERIFY(!v1.moved_from_ctor);
VERIFY(v1.moved_from_assign);
VERIFY(m.size() == 1);
v1.moved_from_assign = false;
auto res3 = m.insert_or_assign(m.begin(), 1, std::move(v1));
VERIFY(res3 != res1 && res3 != m.end());
VERIFY(m[0].val == 6);
VERIFY(m[1].val == 6);
VERIFY(v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
void test03()
{
typedef std::unordered_map<Val, Val> Map;
Map m;
auto res1 = m.insert_or_assign(0, Val(5));
VERIFY(res1.second);
VERIFY(res1.first != m.end());
VERIFY(m[0].val == 5);
Val k1{0};
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.insert_or_assign(std::move(k1), std::move(v1));
VERIFY(!res2.second);
VERIFY(res2.first == res1.first);
VERIFY(m[0].val == 6);
VERIFY(!k1.moved_from_ctor);
VERIFY(!k1.moved_from_assign);
VERIFY(!v1.moved_from_ctor);
VERIFY(v1.moved_from_assign);
VERIFY(m.size() == 1);
Val k2{1};
v1.moved_from_assign = false;
auto res3 = m.insert_or_assign(std::move(k2), std::move(v1));
VERIFY(res3.first != res1.first && res3.first != m.end());
VERIFY(res3.second);
VERIFY(m[0].val == 6);
VERIFY(m[1].val == 6);
VERIFY(k2.moved_from_ctor);
VERIFY(!k2.moved_from_assign);
VERIFY(v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
void test04()
{
typedef std::unordered_map<Val, Val> Map;
Map m;
auto res1 = m.insert_or_assign(m.begin(), 0, Val(5));
VERIFY(res1 != m.end());
VERIFY(m[0].val == 5);
Val k1{0};
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.insert_or_assign(m.begin(), std::move(k1), std::move(v1));
VERIFY(res2 == res1);
VERIFY(m[0].val == 6);
VERIFY(!k1.moved_from_ctor);
VERIFY(!k1.moved_from_assign);
VERIFY(!v1.moved_from_ctor);
VERIFY(v1.moved_from_assign);
VERIFY(m.size() == 1);
Val k2{1};
v1.moved_from_assign = false;
auto res3 = m.insert_or_assign(m.begin(), std::move(k2), std::move(v1));
VERIFY(res3 != res1 && res3 != m.end());
VERIFY(m[0].val == 6);
VERIFY(m[1].val == 6);
VERIFY(k2.moved_from_ctor);
VERIFY(!k2.moved_from_assign);
VERIFY(v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
void test05()
{
typedef std::unordered_map<int, Val> Map;
Map m;
auto res1 = m.insert_or_assign(0, Val(5));
VERIFY(res1.second);
VERIFY(res1.first != m.end());
VERIFY(m[0].val == 5);
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.insert_or_assign(0, v1);
VERIFY(!res2.second);
VERIFY(res2.first == res1.first);
VERIFY(m[0].val == 6);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 1);
auto res3 = m.insert_or_assign(1, v1);
VERIFY(res3.first != res1.first && res3.first != m.end());
VERIFY(res3.second);
VERIFY(m[0].val == 6);
VERIFY(m[1].val == 6);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
void test06()
{
typedef std::unordered_map<int, Val> Map;
Map m;
auto res1 = m.insert_or_assign(m.begin(), 0, Val(5));
VERIFY(res1 != m.end());
VERIFY(m[0].val == 5);
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.insert_or_assign(m.begin(), 0, v1);
VERIFY(res2 == res1);
VERIFY(m[0].val == 6);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 1);
auto res3 = m.insert_or_assign(m.begin(), 1, v1);
VERIFY(res3 != res1 && res3 != m.end());
VERIFY(m[0].val == 6);
VERIFY(m[1].val == 6);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
void test07()
{
typedef std::unordered_map<Val, Val> Map;
Map m;
auto res1 = m.insert_or_assign(0, Val(5));
VERIFY(res1.second);
VERIFY(res1.first != m.end());
VERIFY(m[0].val == 5);
Val k1{0};
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.insert_or_assign(k1, v1);
VERIFY(!res2.second);
VERIFY(res2.first == res1.first);
VERIFY(m[0].val == 6);
VERIFY(!k1.moved_from_ctor);
VERIFY(!k1.moved_from_assign);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 1);
Val k2{1};
auto res3 = m.insert_or_assign(k2, v1);
VERIFY(res3.first != res1.first && res3.first != m.end());
VERIFY(res3.second);
VERIFY(m[0].val == 6);
VERIFY(m[1].val == 6);
VERIFY(!k2.moved_from_ctor);
VERIFY(!k2.moved_from_assign);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
void test08()
{
typedef std::unordered_map<Val, Val> Map;
Map m;
auto res1 = m.insert_or_assign(m.begin(), 0, Val(5));
VERIFY(res1 != m.end());
VERIFY(m[0].val == 5);
Val k1{0};
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.insert_or_assign(m.begin(), k1, v1);
VERIFY(res2 == res1);
VERIFY(m[0].val == 6);
VERIFY(!k1.moved_from_ctor);
VERIFY(!k1.moved_from_assign);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 1);
Val k2{1};
auto res3 = m.insert_or_assign(m.begin(), k2, v1);
VERIFY(res3 != res1 && res3 != m.end());
VERIFY(m[0].val == 6);
VERIFY(m[1].val == 6);
VERIFY(!k2.moved_from_ctor);
VERIFY(!k2.moved_from_assign);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
int main()
{
test01();
test02();
test03();
test04();
test05();
test06();
test07();
test08();
return 0;
}