mirror of
https://github.com/llvm-mirror/libcxx.git
synced 2025-10-24 03:32:35 +08:00
Teach __tree how to handle map's __value_type
This patch is fairly large and contains a number of changes. The changes all work towards allowing __tree to properly handle __value_type esspecially when inserting into the __tree. I chose not to break this change into smaller patches because it wouldn't be possible to write meaningful standard-compliant tests for each patch. It is very similar to r260513 "[libcxx] Teach __hash_table how to handle unordered_map's __hash_value_type". Changes in <map> * Remove __value_type's constructors because it should never be constructed directly. * Make map::emplace and multimap::emplace forward to __tree and remove the old definitions * Remove "__construct_node" map and multimap member functions. Almost all of the construction is done within __tree. * Fix map's move constructor to access "__value_type.__nc" directly and pass this object to __tree::insert. Changes in <__tree> * Add traits to detect, handle, and unwrap, map's "__value_type". * Convert methods taking "value_type" to take "__container_value_type" instead. Previously these methods caused unwanted implicit conversions from "std::pair<Key, Value>" to "__value_type<Key, Value>". * Delete __tree_node and __tree_node_base's constructors and assignment operators. The node types should never be constructed because the "__value_" member of __tree_node must be constructed directly by the allocator. * Make the __tree_node_destructor class and "__construct_node" methods unwrap "__node_value_type" into "__container_value_type" before invoking the allocator. The user's allocator can only be used to construct and destroy the container's value_type. Passing it map's "__value_type" was incorrect. * Cleanup the "__insert" and "__emplace" methods. Have __insert forward to an __emplace function wherever possible to reduce code duplication. __insert_unique(value_type const&) and __insert_unique(value_type&&) forward to __emplace_unique_key_args. These functions will not allocate a new node if the value is already in the tree. * Change the __find* functions to take the "key_type" directly instead of passing in "value_type" and unwrapping the key later. This change allows the find functions to be used without having to construct a "value_type" first. This allows for a number of optimizations. * Teach __move_assign and __assign_multi methods to unwrap map's __value_type. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@264986 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// <map>
|
||||
|
||||
// class map
|
||||
|
||||
// insert(...);
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "count_new.hpp"
|
||||
#include "container_test_types.h"
|
||||
|
||||
template <class Arg>
|
||||
void PrintInfo(int line, Arg&& arg)
|
||||
{
|
||||
std::cout << "In " << __FILE__ << ":" << line << ":\n " << arg << "\n" << std::endl;
|
||||
}
|
||||
#define PRINT(msg) PrintInfo(__LINE__, msg)
|
||||
|
||||
template <class Container>
|
||||
void testContainerInsert()
|
||||
{
|
||||
typedef typename Container::value_type ValueTp;
|
||||
typedef Container C;
|
||||
typedef std::pair<typename C::iterator, bool> R;
|
||||
ConstructController* cc = getConstructController();
|
||||
cc->reset();
|
||||
{
|
||||
PRINT("Testing C::insert(const value_type&)");
|
||||
Container c;
|
||||
const ValueTp v(42, 1);
|
||||
cc->expect<const ValueTp&>();
|
||||
assert(c.insert(v).second);
|
||||
assert(!cc->unchecked());
|
||||
{
|
||||
DisableAllocationGuard g;
|
||||
const ValueTp v2(42, 1);
|
||||
assert(c.insert(v2).second == false);
|
||||
}
|
||||
}
|
||||
{
|
||||
PRINT("Testing C::insert(value_type&)");
|
||||
Container c;
|
||||
ValueTp v(42, 1);
|
||||
cc->expect<const ValueTp&>();
|
||||
assert(c.insert(v).second);
|
||||
assert(!cc->unchecked());
|
||||
{
|
||||
DisableAllocationGuard g;
|
||||
ValueTp v2(42, 1);
|
||||
assert(c.insert(v2).second == false);
|
||||
}
|
||||
}
|
||||
{
|
||||
PRINT("Testing C::insert(value_type&&)");
|
||||
Container c;
|
||||
ValueTp v(42, 1);
|
||||
cc->expect<ValueTp&&>();
|
||||
assert(c.insert(std::move(v)).second);
|
||||
assert(!cc->unchecked());
|
||||
{
|
||||
DisableAllocationGuard g;
|
||||
ValueTp v2(42, 1);
|
||||
assert(c.insert(std::move(v2)).second == false);
|
||||
}
|
||||
}
|
||||
{
|
||||
PRINT("Testing C::insert(std::initializer_list<ValueTp>)");
|
||||
Container c;
|
||||
std::initializer_list<ValueTp> il = { ValueTp(1, 1), ValueTp(2, 1) };
|
||||
cc->expect<ValueTp const&>(2);
|
||||
c.insert(il);
|
||||
assert(!cc->unchecked());
|
||||
{
|
||||
DisableAllocationGuard g;
|
||||
c.insert(il);
|
||||
}
|
||||
}
|
||||
{
|
||||
PRINT("Testing C::insert(Iter, Iter) for *Iter = value_type const&");
|
||||
Container c;
|
||||
const ValueTp ValueList[] = { ValueTp(1, 1), ValueTp(2, 1), ValueTp(3, 1) };
|
||||
cc->expect<ValueTp const&>(3);
|
||||
c.insert(std::begin(ValueList), std::end(ValueList));
|
||||
assert(!cc->unchecked());
|
||||
{
|
||||
DisableAllocationGuard g;
|
||||
c.insert(std::begin(ValueList), std::end(ValueList));
|
||||
}
|
||||
}
|
||||
{
|
||||
PRINT("Testing C::insert(Iter, Iter) for *Iter = value_type&&");
|
||||
Container c;
|
||||
ValueTp ValueList[] = { ValueTp(1, 1), ValueTp(2, 1) , ValueTp(3, 1) };
|
||||
cc->expect<ValueTp&&>(3);
|
||||
c.insert(std::move_iterator<ValueTp*>(std::begin(ValueList)),
|
||||
std::move_iterator<ValueTp*>(std::end(ValueList)));
|
||||
assert(!cc->unchecked());
|
||||
{
|
||||
DisableAllocationGuard g;
|
||||
ValueTp ValueList2[] = { ValueTp(1, 1), ValueTp(2, 1) , ValueTp(3, 1) };
|
||||
c.insert(std::move_iterator<ValueTp*>(std::begin(ValueList2)),
|
||||
std::move_iterator<ValueTp*>(std::end(ValueList2)));
|
||||
}
|
||||
}
|
||||
{
|
||||
PRINT("Testing C::insert(Iter, Iter) for *Iter = value_type&");
|
||||
Container c;
|
||||
ValueTp ValueList[] = { ValueTp(1, 1), ValueTp(2, 1) , ValueTp(3, 1) };
|
||||
cc->expect<ValueTp const&>(3);
|
||||
c.insert(std::begin(ValueList), std::end(ValueList));
|
||||
assert(!cc->unchecked());
|
||||
{
|
||||
DisableAllocationGuard g;
|
||||
c.insert(std::begin(ValueList), std::end(ValueList));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
testContainerInsert<TCT::map<> >();
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// <map>
|
||||
|
||||
// class multimap
|
||||
|
||||
// insert(...)
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "count_new.hpp"
|
||||
#include "container_test_types.h"
|
||||
|
||||
template <class Arg>
|
||||
void PrintInfo(int line, Arg&& arg)
|
||||
{
|
||||
std::cout << "In " << __FILE__ << ":" << line << ":\n " << arg << "\n" << std::endl;
|
||||
}
|
||||
#define PRINT(msg) PrintInfo(__LINE__, msg)
|
||||
|
||||
template <class Container>
|
||||
void testContainerInsert()
|
||||
{
|
||||
typedef typename Container::value_type ValueTp;
|
||||
typedef Container C;
|
||||
ConstructController* cc = getConstructController();
|
||||
cc->reset();
|
||||
{
|
||||
PRINT("Testing C::insert(const value_type&)");
|
||||
Container c;
|
||||
const ValueTp v(42, 1);
|
||||
cc->expect<const ValueTp&>();
|
||||
c.insert(v);
|
||||
assert(!cc->unchecked());
|
||||
}
|
||||
{
|
||||
PRINT("Testing C::insert(value_type&)");
|
||||
Container c;
|
||||
ValueTp v(42, 1);
|
||||
cc->expect<ValueTp&>();
|
||||
c.insert(v);
|
||||
assert(!cc->unchecked());
|
||||
}
|
||||
{
|
||||
PRINT("Testing C::insert(value_type&&)");
|
||||
Container c;
|
||||
ValueTp v(42, 1);
|
||||
cc->expect<ValueTp&&>();
|
||||
c.insert(std::move(v));
|
||||
assert(!cc->unchecked());
|
||||
}
|
||||
{
|
||||
PRINT("Testing C::insert(std::initializer_list<ValueTp>)");
|
||||
Container c;
|
||||
std::initializer_list<ValueTp> il = { ValueTp(1, 1), ValueTp(2, 1) };
|
||||
cc->expect<ValueTp const&>(2);
|
||||
c.insert(il);
|
||||
assert(!cc->unchecked());
|
||||
}
|
||||
{
|
||||
PRINT("Testing C::insert(Iter, Iter) for *Iter = value_type const&");
|
||||
Container c;
|
||||
const ValueTp ValueList[] = { ValueTp(1, 1), ValueTp(2, 1), ValueTp(3, 1) };
|
||||
cc->expect<ValueTp const&>(3);
|
||||
c.insert(std::begin(ValueList), std::end(ValueList));
|
||||
assert(!cc->unchecked());
|
||||
}
|
||||
{
|
||||
PRINT("Testing C::insert(Iter, Iter) for *Iter = value_type&&");
|
||||
Container c;
|
||||
ValueTp ValueList[] = { ValueTp(1, 1), ValueTp(2, 1) , ValueTp(3, 1) };
|
||||
cc->expect<ValueTp&&>(3);
|
||||
c.insert(std::move_iterator<ValueTp*>(std::begin(ValueList)),
|
||||
std::move_iterator<ValueTp*>(std::end(ValueList)));
|
||||
assert(!cc->unchecked());
|
||||
}
|
||||
{
|
||||
PRINT("Testing C::insert(Iter, Iter) for *Iter = value_type&");
|
||||
Container c;
|
||||
ValueTp ValueList[] = { ValueTp(1, 1), ValueTp(2, 1) , ValueTp(3, 1) };
|
||||
cc->expect<ValueTp&>(3);
|
||||
c.insert(std::begin(ValueList), std::end(ValueList));
|
||||
assert(!cc->unchecked());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
testContainerInsert<TCT::multimap<> >();
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// <set>
|
||||
|
||||
// class multiset
|
||||
|
||||
// insert(...)
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
#include <set>
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "count_new.hpp"
|
||||
#include "container_test_types.h"
|
||||
|
||||
template <class Arg>
|
||||
void PrintInfo(int line, Arg&& arg)
|
||||
{
|
||||
std::cout << "In " << __FILE__ << ":" << line << ":\n " << arg << "\n" << std::endl;
|
||||
}
|
||||
#define PRINT(...) PrintInfo(__LINE__, __VA_ARGS__)
|
||||
|
||||
template <class Container>
|
||||
void testContainerInsert()
|
||||
{
|
||||
typedef typename Container::value_type ValueTp;
|
||||
typedef Container C;
|
||||
ConstructController* cc = getConstructController();
|
||||
cc->reset();
|
||||
{
|
||||
PRINT("Testing C::insert(const value_type&)");
|
||||
Container c;
|
||||
const ValueTp v(42);
|
||||
cc->expect<const ValueTp&>();
|
||||
c.insert(v);
|
||||
assert(!cc->unchecked());
|
||||
}
|
||||
{
|
||||
PRINT("Testing C::insert(value_type&)");
|
||||
Container c;
|
||||
ValueTp v(42);
|
||||
cc->expect<const ValueTp&>();
|
||||
c.insert(v);
|
||||
assert(!cc->unchecked());
|
||||
}
|
||||
{
|
||||
PRINT("Testing C::insert(value_type&&)");
|
||||
Container c;
|
||||
ValueTp v(42);
|
||||
cc->expect<ValueTp&&>();
|
||||
c.insert(std::move(v));
|
||||
assert(!cc->unchecked());
|
||||
}
|
||||
{
|
||||
PRINT("Testing C::insert(std::initializer_list<ValueTp>)");
|
||||
Container c;
|
||||
std::initializer_list<ValueTp> il = { ValueTp(1), ValueTp(2) };
|
||||
cc->expect<ValueTp const&>(2);
|
||||
c.insert(il);
|
||||
assert(!cc->unchecked());
|
||||
}
|
||||
{
|
||||
PRINT("Testing C::insert(Iter, Iter) for *Iter = value_type const&");
|
||||
Container c;
|
||||
const ValueTp ValueList[] = { ValueTp(1), ValueTp(2), ValueTp(3) };
|
||||
cc->expect<ValueTp const&>(3);
|
||||
c.insert(std::begin(ValueList), std::end(ValueList));
|
||||
assert(!cc->unchecked());
|
||||
}
|
||||
{
|
||||
PRINT("Testing C::insert(Iter, Iter) for *Iter = value_type&&");
|
||||
Container c;
|
||||
ValueTp ValueList[] = { ValueTp(1), ValueTp(2) , ValueTp(3) };
|
||||
cc->expect<ValueTp&&>(3);
|
||||
c.insert(std::move_iterator<ValueTp*>(std::begin(ValueList)),
|
||||
std::move_iterator<ValueTp*>(std::end(ValueList)));
|
||||
assert(!cc->unchecked());
|
||||
}
|
||||
{
|
||||
PRINT("Testing C::insert(Iter, Iter) for *Iter = value_type&");
|
||||
Container c;
|
||||
ValueTp ValueList[] = { ValueTp(1), ValueTp(2) , ValueTp(3) };
|
||||
cc->expect<ValueTp&>(3);
|
||||
c.insert(std::begin(ValueList), std::end(ValueList));
|
||||
assert(!cc->unchecked());
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
testContainerInsert<TCT::multiset<> >();
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// <set>
|
||||
|
||||
// class set
|
||||
|
||||
// insert(...)
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
#include <set>
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "count_new.hpp"
|
||||
#include "container_test_types.h"
|
||||
|
||||
template <class Arg>
|
||||
void PrintInfo(int line, Arg&& arg)
|
||||
{
|
||||
std::cout << "In " << __FILE__ << ":" << line << ":\n " << arg << "\n" << std::endl;
|
||||
}
|
||||
#define PRINT(msg) PrintInfo(__LINE__, msg)
|
||||
|
||||
template <class Container>
|
||||
void testContainerInsert()
|
||||
{
|
||||
typedef typename Container::value_type ValueTp;
|
||||
typedef Container C;
|
||||
typedef std::pair<typename C::iterator, bool> R;
|
||||
ConstructController* cc = getConstructController();
|
||||
cc->reset();
|
||||
{
|
||||
PRINT("Testing C::insert(const value_type&)");
|
||||
Container c;
|
||||
const ValueTp v(42);
|
||||
cc->expect<const ValueTp&>();
|
||||
assert(c.insert(v).second);
|
||||
assert(!cc->unchecked());
|
||||
{
|
||||
DisableAllocationGuard g;
|
||||
const ValueTp v2(42);
|
||||
assert(c.insert(v2).second == false);
|
||||
}
|
||||
}
|
||||
{
|
||||
PRINT("Testing C::insert(value_type&)");
|
||||
Container c;
|
||||
ValueTp v(42);
|
||||
cc->expect<const ValueTp&>();
|
||||
assert(c.insert(v).second);
|
||||
assert(!cc->unchecked());
|
||||
{
|
||||
DisableAllocationGuard g;
|
||||
ValueTp v2(42);
|
||||
assert(c.insert(v2).second == false);
|
||||
}
|
||||
}
|
||||
{
|
||||
PRINT("Testing C::insert(value_type&&)");
|
||||
Container c;
|
||||
ValueTp v(42);
|
||||
cc->expect<ValueTp&&>();
|
||||
assert(c.insert(std::move(v)).second);
|
||||
assert(!cc->unchecked());
|
||||
{
|
||||
DisableAllocationGuard g;
|
||||
ValueTp v2(42);
|
||||
assert(c.insert(std::move(v2)).second == false);
|
||||
}
|
||||
}
|
||||
{
|
||||
PRINT("Testing C::insert(std::initializer_list<ValueTp>)");
|
||||
Container c;
|
||||
std::initializer_list<ValueTp> il = { ValueTp(1), ValueTp(2) };
|
||||
cc->expect<ValueTp const&>(2);
|
||||
c.insert(il);
|
||||
assert(!cc->unchecked());
|
||||
{
|
||||
DisableAllocationGuard g;
|
||||
c.insert(il);
|
||||
}
|
||||
}
|
||||
{
|
||||
PRINT("Testing C::insert(Iter, Iter) for *Iter = value_type const&");
|
||||
Container c;
|
||||
const ValueTp ValueList[] = { ValueTp(1), ValueTp(2), ValueTp(3) };
|
||||
cc->expect<ValueTp const&>(3);
|
||||
c.insert(std::begin(ValueList), std::end(ValueList));
|
||||
assert(!cc->unchecked());
|
||||
{
|
||||
DisableAllocationGuard g;
|
||||
c.insert(std::begin(ValueList), std::end(ValueList));
|
||||
}
|
||||
}
|
||||
{
|
||||
PRINT("Testing C::insert(Iter, Iter) for *Iter = value_type&&");
|
||||
Container c;
|
||||
ValueTp ValueList[] = { ValueTp(1), ValueTp(2) , ValueTp(3) };
|
||||
cc->expect<ValueTp&&>(3);
|
||||
c.insert(std::move_iterator<ValueTp*>(std::begin(ValueList)),
|
||||
std::move_iterator<ValueTp*>(std::end(ValueList)));
|
||||
assert(!cc->unchecked());
|
||||
{
|
||||
DisableAllocationGuard g;
|
||||
ValueTp ValueList2[] = { ValueTp(1), ValueTp(2) , ValueTp(3) };
|
||||
c.insert(std::move_iterator<ValueTp*>(std::begin(ValueList2)),
|
||||
std::move_iterator<ValueTp*>(std::end(ValueList2)));
|
||||
}
|
||||
}
|
||||
{
|
||||
PRINT("Testing C::insert(Iter, Iter) for *Iter = value_type&");
|
||||
Container c;
|
||||
ValueTp ValueList[] = { ValueTp(1), ValueTp(2) , ValueTp(3) };
|
||||
cc->expect<ValueTp const&>(3);
|
||||
c.insert(std::begin(ValueList), std::end(ValueList));
|
||||
assert(!cc->unchecked());
|
||||
{
|
||||
DisableAllocationGuard g;
|
||||
c.insert(std::begin(ValueList), std::end(ValueList));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
testContainerInsert<TCT::set<> >();
|
||||
}
|
||||
Reference in New Issue
Block a user