dexonsmith updated this revision to Diff 50883. dexonsmith added a comment.
Eric sent me his preferred tests, which look fine to me. I've applied them to this patch. http://reviews.llvm.org/D16360 Files: include/__hash_table test/libcxx/containers/unord/unord.set/insert_dup_alloc.pass.cpp test/std/containers/unord/unord.map/unord.map.modifiers/insert_allocator_requirements.pass.cpp test/std/containers/unord/unord.map/unord.map.modifiers/insert_and_emplace_allocator_requirements.pass.cpp test/std/containers/unord/unord.set/insert_allocator_requirements.pass.cpp test/std/containers/unord/unord.set/insert_and_emplace_allocator_requirements.pass.cpp
Index: test/std/containers/unord/unord.set/insert_and_emplace_allocator_requirements.pass.cpp =================================================================== --- /dev/null +++ test/std/containers/unord/unord.set/insert_and_emplace_allocator_requirements.pass.cpp @@ -0,0 +1,220 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// <unordered_set> + +// class unordered_set + +// insert(...) +// emplace(...) + +// UNSUPPORTED: c++98, c++03 + +#include <unordered_set> +#include <iostream> +#include <cassert> + +#include "test_macros.h" +#include "count_new.hpp" +#include "container_test_types.h" + +#if TEST_STD_VER >= 11 +template <class Arg> +void PrintInfo(int line, Arg&& arg) +#else +template <class Arg> +void PrintInfo(int line, Arg arg) +#endif +{ + 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; + 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(const value_type&&)"); + Container c; + const ValueTp v(42); + cc->expect<const ValueTp&>(); + assert(c.insert(std::move(v)).second); + assert(!cc->unchecked()); + { + DisableAllocationGuard g; + const 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)); + } + } +} + + +template <class Container> +void testContainerEmplace() +{ + 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::emplace(const value_type&)"); + Container c; + const ValueTp v(42); + cc->expect<const ValueTp&>(); + assert(c.emplace(v).second); + assert(!cc->unchecked()); + { + DisableAllocationGuard g; + const ValueTp v2(42); + assert(c.emplace(v2).second == false); + } + } + { + PRINT("Testing C::emplace(value_type&)"); + Container c; + ValueTp v(42); + cc->expect<ValueTp&>(); + assert(c.emplace(v).second); + assert(!cc->unchecked()); + { + DisableAllocationGuard g; + ValueTp v2(42); + assert(c.emplace(v2).second == false); + } + } + { + PRINT("Testing C::emplace(value_type&&)"); + Container c; + ValueTp v(42); + cc->expect<ValueTp&&>(); + assert(c.emplace(std::move(v)).second); + assert(!cc->unchecked()); + { + DisableAllocationGuard g; + ValueTp v2(42); + assert(c.emplace(std::move(v2)).second == false); + } + } + { + PRINT("Testing C::emplace(const value_type&&)"); + Container c; + const ValueTp v(42); + cc->expect<const ValueTp&&>(); + assert(c.emplace(std::move(v)).second); + assert(!cc->unchecked()); + { + DisableAllocationGuard g; + const ValueTp v2(42); + assert(c.emplace(std::move(v2)).second == false); + } + } +} + + +int main() +{ + testContainerInsert<TCT::unordered_set<> >(); + testContainerEmplace<TCT::unordered_set<> >(); +} Index: test/std/containers/unord/unord.set/insert_allocator_requirements.pass.cpp =================================================================== --- test/std/containers/unord/unord.set/insert_allocator_requirements.pass.cpp +++ /dev/null @@ -1,142 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// 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. -// -//===----------------------------------------------------------------------===// - -// <unordered_set> - -// class unordered_set - -// insert(...) - -// UNSUPPORTED: c++98, c++03 - -#include <unordered_set> -#include <iostream> -#include <cassert> - -#include "test_macros.h" -#include "count_new.hpp" -#include "container_test_types.h" - -#if TEST_STD_VER >= 11 -template <class Arg> -void PrintInfo(int line, Arg&& arg) -#else -template <class Arg> -void PrintInfo(int line, Arg arg) -#endif -{ - 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; - 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::unordered_set<> >(); -} Index: test/std/containers/unord/unord.map/unord.map.modifiers/insert_and_emplace_allocator_requirements.pass.cpp =================================================================== --- /dev/null +++ test/std/containers/unord/unord.map/unord.map.modifiers/insert_and_emplace_allocator_requirements.pass.cpp @@ -0,0 +1,249 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// <unordered_map> + +// class unordered_map + +// insert(...); + +// UNSUPPORTED: c++98, c++03 + + +#include <unordered_map> +#include <iostream> +#include <cassert> + +#include "test_macros.h" +#include "count_new.hpp" +#include "container_test_types.h" + +#if TEST_STD_VER >= 11 +template <class Arg> +void PrintInfo(int line, Arg&& arg) +#else +template <class Arg> +void PrintInfo(int line, Arg arg) +#endif +{ + 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; + 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(const value_type&&)"); + Container c; + const ValueTp v(42, 1); + cc->expect<const ValueTp&>(); + assert(c.insert(std::move(v)).second); + assert(!cc->unchecked()); + { + DisableAllocationGuard g; + const 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)); + } + } +} + + +template <class Container> +void testContainerEmplace() +{ + typedef typename Container::value_type ValueTp; + typedef typename Container::key_type Key; + typedef typename Container::mapped_type Mapped; + typedef typename std::pair<Key, Mapped> NonConstKeyPair; + typedef Container C; + typedef std::pair<typename C::iterator, bool> R; + ConstructController* cc = getConstructController(); + cc->reset(); + { + PRINT("Testing C::emplace(const value_type&)"); + Container c; + const ValueTp v(42, 1); + cc->expect<const ValueTp&>(); + assert(c.emplace(v).second); + assert(!cc->unchecked()); + { + DisableAllocationGuard g; + const ValueTp v2(42, 1); + assert(c.emplace(v2).second == false); + } + } + { + PRINT("Testing C::emplace(value_type&)"); + Container c; + ValueTp v(42, 1); + cc->expect<ValueTp&>(); + assert(c.emplace(v).second); + assert(!cc->unchecked()); + { + DisableAllocationGuard g; + ValueTp v2(42, 1); + assert(c.emplace(v2).second == false); + } + } + { + PRINT("Testing C::emplace(value_type&&)"); + Container c; + ValueTp v(42, 1); + cc->expect<ValueTp&&>(); + assert(c.emplace(std::move(v)).second); + assert(!cc->unchecked()); + { + DisableAllocationGuard g; + ValueTp v2(42, 1); + assert(c.emplace(std::move(v2)).second == false); + } + } + { + PRINT("Testing C::emplace(const value_type&&)"); + Container c; + const ValueTp v(42, 1); + cc->expect<const ValueTp&&>(); + assert(c.emplace(std::move(v)).second); + assert(!cc->unchecked()); + { + DisableAllocationGuard g; + const ValueTp v2(42, 1); + assert(c.emplace(std::move(v2)).second == false); + } + } + { + PRINT("Testing C::emplace(pair<Key, Mapped> const&)"); + Container c; + const NonConstKeyPair v(42, 1); + cc->expect<const NonConstKeyPair&>(); + assert(c.emplace(v).second); + assert(!cc->unchecked()); + { + DisableAllocationGuard g; + const NonConstKeyPair v2(42, 1); + assert(c.emplace(v2).second == false); + } + } + { + PRINT("Testing C::emplace(pair<Key, Mapped> &&)"); + Container c; + NonConstKeyPair v(42, 1); + cc->expect<NonConstKeyPair&&>(); + assert(c.emplace(std::move(v)).second); + assert(!cc->unchecked()); + { + DisableAllocationGuard g; + NonConstKeyPair v2(42, 1); + assert(c.emplace(std::move(v2)).second == false); + } + } +} + + +int main() +{ + testContainerInsert<TCT::unordered_map<> >(); + testContainerEmplace<TCT::unordered_map<> >(); +} Index: test/std/containers/unord/unord.map/unord.map.modifiers/insert_allocator_requirements.pass.cpp =================================================================== --- test/std/containers/unord/unord.map/unord.map.modifiers/insert_allocator_requirements.pass.cpp +++ /dev/null @@ -1,143 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// 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. -// -//===----------------------------------------------------------------------===// - -// <unordered_map> - -// class unordered_map - -// insert(...); - -// UNSUPPORTED: c++98, c++03 - - -#include <unordered_map> -#include <iostream> -#include <cassert> - -#include "test_macros.h" -#include "count_new.hpp" -#include "container_test_types.h" - -#if TEST_STD_VER >= 11 -template <class Arg> -void PrintInfo(int line, Arg&& arg) -#else -template <class Arg> -void PrintInfo(int line, Arg arg) -#endif -{ - 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; - 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::unordered_map<> >(); -} Index: test/libcxx/containers/unord/unord.set/insert_dup_alloc.pass.cpp =================================================================== --- test/libcxx/containers/unord/unord.set/insert_dup_alloc.pass.cpp +++ /dev/null @@ -1,48 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// 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. -// -//===----------------------------------------------------------------------===// - -// Check that we don't allocate when trying to insert a duplicate value into a -// unordered_set. See PR12999 http://llvm.org/bugs/show_bug.cgi?id=12999 - -#include <cassert> -#include <unordered_set> -#include "count_new.hpp" -#include "MoveOnly.h" - -int main() -{ - { - std::unordered_set<int> s; - assert(globalMemCounter.checkNewCalledEq(0)); - - for(int i=0; i < 100; ++i) - s.insert(3); - - assert(s.size() == 1); - assert(s.count(3) == 1); - assert(globalMemCounter.checkNewCalledEq(2)); - } - assert(globalMemCounter.checkOutstandingNewEq(0)); - globalMemCounter.reset(); -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - { - std::unordered_set<MoveOnly> s; - assert(globalMemCounter.checkNewCalledEq(0)); - - for(int i=0; i<100; i++) - s.insert(MoveOnly(3)); - - assert(s.size() == 1); - assert(s.count(MoveOnly(3)) == 1); - assert(globalMemCounter.checkNewCalledEq(2)); - } - assert(globalMemCounter.checkOutstandingNewEq(0)); - globalMemCounter.reset(); -#endif -} Index: include/__hash_table =================================================================== --- include/__hash_table +++ include/__hash_table @@ -100,6 +100,21 @@ return size_t(1) << (std::numeric_limits<size_t>::digits - __clz(__n-1)); } +struct __extract_key_fail_tag {}; +struct __extract_key_self_tag {}; +struct __extract_key_first_tag {}; + +template <class _ValTy, class _Key, + class _RawValTy = typename __unconstref<_ValTy>::type> +struct __can_extract_key + : conditional<is_same<_RawValTy, _Key>::value, __extract_key_self_tag, + __extract_key_fail_tag>::type {}; + +template <class _Pair, class _Key, class _First, class _Second> +struct __can_extract_key<_Pair, _Key, pair<_First, _Second>> + : conditional<is_same<typename remove_const<_First>::type, _Key>::value, + __extract_key_first_tag, __extract_key_fail_tag>::type {}; + template <class _Tp, class _Hash, class _Equal, class _Alloc> class __hash_table; template <class _NodePtr> class _LIBCPP_TYPE_VIS_ONLY __hash_iterator; @@ -903,6 +918,7 @@ typedef typename _NodeTypes::__node_value_type __node_value_type; typedef typename _NodeTypes::__container_value_type __container_value_type; + typedef typename _NodeTypes::key_type key_type; typedef value_type& reference; typedef const value_type& const_reference; typedef typename __alloc_traits::pointer pointer; @@ -1041,13 +1057,49 @@ #ifndef _LIBCPP_CXX03_LANG template <class _Key, class ..._Args> + _LIBCPP_INLINE_VISIBILITY pair<iterator, bool> __emplace_unique_key_args(_Key const& __k, _Args&&... __args); template <class... _Args> - pair<iterator, bool> __emplace_unique(_Args&&... __args); + _LIBCPP_INLINE_VISIBILITY + pair<iterator, bool> __emplace_unique_impl(_Args&&... __args); + + template <class _Pp> + _LIBCPP_INLINE_VISIBILITY + pair<iterator, bool> __emplace_unique(_Pp&& __x) { + return __emplace_unique_extract_key(_VSTD::forward<_Pp>(__x), + __can_extract_key<_Pp, key_type>()); + } + template <class... _Args> + _LIBCPP_INLINE_VISIBILITY + pair<iterator, bool> __emplace_unique(_Args&&... __args) { + return __emplace_unique_impl(_VSTD::forward<_Args>(__args)...); + } + + template <class _Pp> + _LIBCPP_INLINE_VISIBILITY + pair<iterator, bool> + __emplace_unique_extract_key(_Pp&& __x, __extract_key_fail_tag) { + return __emplace_unique_impl(_VSTD::forward<_Pp>(__x)); + } + template <class _Pp> + _LIBCPP_INLINE_VISIBILITY + pair<iterator, bool> + __emplace_unique_extract_key(_Pp&& __x, __extract_key_self_tag) { + return __emplace_unique_key_args(__x, _VSTD::forward<_Pp>(__x)); + } + template <class _Pp> + _LIBCPP_INLINE_VISIBILITY + pair<iterator, bool> + __emplace_unique_extract_key(_Pp&& __x, __extract_key_first_tag) { + return __emplace_unique_key_args(__x.first, _VSTD::forward<_Pp>(__x)); + } + template <class... _Args> + _LIBCPP_INLINE_VISIBILITY iterator __emplace_multi(_Args&&... __args); template <class... _Args> + _LIBCPP_INLINE_VISIBILITY iterator __emplace_hint_multi(const_iterator __p, _Args&&... __args); @@ -1989,7 +2041,7 @@ template <class _Tp, class _Hash, class _Equal, class _Alloc> template <class... _Args> pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool> -__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique(_Args&&... __args) +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique_impl(_Args&&... __args) { __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); pair<iterator, bool> __r = __node_insert_unique(__h.get());
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits