Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 1afd508

Browse filesBrowse files
committed
Rewrite the CFOA containers' FOA constructors so that a class with a template conversion operator does not instantiate the FOA container
1 parent 6732e76 commit 1afd508
Copy full SHA for 1afd508

File tree

Expand file treeCollapse file tree

7 files changed

+163
-16
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

7 files changed

+163
-16
lines changed
Open diff view settings
Collapse file

‎include/boost/unordered/concurrent_flat_map.hpp‎

Copy file name to clipboardExpand all lines: include/boost/unordered/concurrent_flat_map.hpp
+24-4Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
*
33
* Copyright 2023 Christian Mazakas.
44
* Copyright 2023-2024 Joaquin M Lopez Munoz.
5+
* Copyright 2026 Braden Ganetsky
56
* Distributed under the Boost Software License, Version 1.0.
67
* (See accompanying file LICENSE_1_0.txt or copy at
78
* http://www.boost.org/LICENSE_1_0.txt)
@@ -189,11 +190,30 @@ namespace boost {
189190
{
190191
}
191192

193+
template <class U,
194+
typename std::enable_if<
195+
// Ensure we match exactly `unordered_flat_map&&`.
196+
// Any lvalue references to `unordered_flat_map` are not supported.
197+
std::is_same<U,
198+
unordered_flat_map<Key, T, Hash, Pred, Allocator> >::value,
199+
int>::type = 0>
200+
concurrent_flat_map(U&& other) : table_(std::move(other.table_))
201+
{
202+
}
192203

193-
template <bool avoid_explicit_instantiation = true>
194-
concurrent_flat_map(
195-
unordered_flat_map<Key, T, Hash, Pred, Allocator>&& other)
196-
: table_(std::move(other.table_))
204+
template <class U,
205+
typename std::enable_if<
206+
// Ensure we don't match any cvref-qualified `unordered_flat_map&&`,
207+
!detail::is_similar<U,
208+
unordered_flat_map<Key, T, Hash, Pred, Allocator> >::value
209+
// but we do match anything convertible to `unordered_flat_map`.
210+
&& std::is_convertible<U&&,
211+
unordered_flat_map<Key, T, Hash, Pred, Allocator> >::value,
212+
int>::type = 0>
213+
concurrent_flat_map(U&& other)
214+
: concurrent_flat_map(
215+
unordered_flat_map<Key, T, Hash, Pred, Allocator>(
216+
std::forward<U>(other)))
197217
{
198218
}
199219

Collapse file

‎include/boost/unordered/concurrent_flat_set.hpp‎

Copy file name to clipboardExpand all lines: include/boost/unordered/concurrent_flat_set.hpp
+23-4Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
*
33
* Copyright 2023 Christian Mazakas.
44
* Copyright 2023-2024 Joaquin M Lopez Munoz.
5+
* Copyright 2026 Braden Ganetsky
56
* Distributed under the Boost Software License, Version 1.0.
67
* (See accompanying file LICENSE_1_0.txt or copy at
78
* http://www.boost.org/LICENSE_1_0.txt)
@@ -186,11 +187,29 @@ namespace boost {
186187
{
187188
}
188189

190+
template <class U,
191+
typename std::enable_if<
192+
// Ensure we match exactly `unordered_flat_set&&`.
193+
// Any lvalue references to `unordered_flat_set` are not supported.
194+
std::is_same<U,
195+
unordered_flat_set<Key, Hash, Pred, Allocator> >::value,
196+
int>::type = 0>
197+
concurrent_flat_set(U&& other) : table_(std::move(other.table_))
198+
{
199+
}
189200

190-
template <bool avoid_explicit_instantiation = true>
191-
concurrent_flat_set(
192-
unordered_flat_set<Key, Hash, Pred, Allocator>&& other)
193-
: table_(std::move(other.table_))
201+
template <class U,
202+
typename std::enable_if<
203+
// Ensure we don't match any cvref-qualified `unordered_flat_set&&`,
204+
!detail::is_similar<U,
205+
unordered_flat_set<Key, Hash, Pred, Allocator> >::value
206+
// but we do match anything convertible to `unordered_flat_set`.
207+
&& std::is_convertible<U&&,
208+
unordered_flat_set<Key, Hash, Pred, Allocator> >::value,
209+
int>::type = 0>
210+
concurrent_flat_set(U&& other)
211+
: concurrent_flat_set(unordered_flat_set<Key, Hash, Pred, Allocator>(
212+
std::forward<U>(other)))
194213
{
195214
}
196215

Collapse file

‎include/boost/unordered/concurrent_node_map.hpp‎

Copy file name to clipboardExpand all lines: include/boost/unordered/concurrent_node_map.hpp
+25-4Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
*
33
* Copyright 2023 Christian Mazakas.
44
* Copyright 2023-2024 Joaquin M Lopez Munoz.
5+
* Copyright 2026 Braden Ganetsky
56
* Distributed under the Boost Software License, Version 1.0.
67
* (See accompanying file LICENSE_1_0.txt or copy at
78
* http://www.boost.org/LICENSE_1_0.txt)
@@ -197,10 +198,30 @@ namespace boost {
197198
{
198199
}
199200

200-
template <bool avoid_explicit_instantiation = true>
201-
concurrent_node_map(
202-
unordered_node_map<Key, T, Hash, Pred, Allocator>&& other)
203-
: table_(std::move(other.table_))
201+
template <class U,
202+
typename std::enable_if<
203+
// Ensure we match exactly `unordered_node_map&&`.
204+
// Any lvalue references to `unordered_node_map` are not supported.
205+
std::is_same<U,
206+
unordered_node_map<Key, T, Hash, Pred, Allocator> >::value,
207+
int>::type = 0>
208+
concurrent_node_map(U&& other) : table_(std::move(other.table_))
209+
{
210+
}
211+
212+
template <class U,
213+
typename std::enable_if<
214+
// Ensure we don't match any cvref-qualified `unordered_node_map&&`,
215+
!detail::is_similar<U,
216+
unordered_node_map<Key, T, Hash, Pred, Allocator> >::value
217+
// but we do match anything convertible to `unordered_node_map`.
218+
&& std::is_convertible<U&&,
219+
unordered_node_map<Key, T, Hash, Pred, Allocator> >::value,
220+
int>::type = 0>
221+
concurrent_node_map(U&& other)
222+
: concurrent_node_map(
223+
unordered_node_map<Key, T, Hash, Pred, Allocator>(
224+
std::forward<U>(other)))
204225
{
205226
}
206227

Collapse file

‎include/boost/unordered/concurrent_node_set.hpp‎

Copy file name to clipboardExpand all lines: include/boost/unordered/concurrent_node_set.hpp
+24-4Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
*
33
* Copyright 2023 Christian Mazakas.
44
* Copyright 2023-2024 Joaquin M Lopez Munoz.
5+
* Copyright 2026 Braden Ganetsky
56
* Distributed under the Boost Software License, Version 1.0.
67
* (See accompanying file LICENSE_1_0.txt or copy at
78
* http://www.boost.org/LICENSE_1_0.txt)
@@ -194,10 +195,29 @@ namespace boost {
194195
{
195196
}
196197

197-
template <bool avoid_explicit_instantiation = true>
198-
concurrent_node_set(
199-
unordered_node_set<Key, Hash, Pred, Allocator>&& other)
200-
: table_(std::move(other.table_))
198+
template <class U,
199+
typename std::enable_if<
200+
// Ensure we match exactly `unordered_node_set&&`.
201+
// Any lvalue references to `unordered_node_set` are not supported.
202+
std::is_same<U,
203+
unordered_node_set<Key, Hash, Pred, Allocator> >::value,
204+
int>::type = 0>
205+
concurrent_node_set(U&& other) : table_(std::move(other.table_))
206+
{
207+
}
208+
209+
template <class U,
210+
typename std::enable_if<
211+
// Ensure we don't match any cvref-qualified `unordered_node_set&&`,
212+
!detail::is_similar<U,
213+
unordered_node_set<Key, Hash, Pred, Allocator> >::value
214+
// but we do match anything convertible to `unordered_node_set`.
215+
&& std::is_convertible<U&&,
216+
unordered_node_set<Key, Hash, Pred, Allocator> >::value,
217+
int>::type = 0>
218+
concurrent_node_set(U&& other)
219+
: concurrent_node_set(unordered_node_set<Key, Hash, Pred, Allocator>(
220+
std::forward<U>(other)))
201221
{
202222
}
203223

Collapse file

‎test/CMakeLists.txt‎

Copy file name to clipboardExpand all lines: test/CMakeLists.txt
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,5 +170,6 @@ foa_tests(TYPE compile NAME explicit_instantiation_tests SOURCES unordered/expli
170170
cfoa_tests(TYPE compile NAME explicit_instantiation_tests SOURCES cfoa/explicit_instantiation_tests.cpp)
171171

172172
foa_tests(TYPE compile NAME conversion_operator_tests SOURCES unordered/conversion_operator_tests.cpp)
173+
cfoa_tests(TYPE compile NAME conversion_operator_tests SOURCES cfoa/conversion_operator_tests.cpp)
173174

174175
endif()
Collapse file

‎test/Jamfile.v2‎

Copy file name to clipboardExpand all lines: test/Jamfile.v2
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ compile unordered/explicit_instantiation_tests.cpp : <define>BOOST_UNORDERED_FOA
170170
compile cfoa/explicit_instantiation_tests.cpp : : cfoa_explicit_instantiation_tests ;
171171

172172
compile unordered/conversion_operator_tests.cpp : <define>BOOST_UNORDERED_FOA_TESTS : foa_conversion_operator_tests ;
173+
compile cfoa/conversion_operator_tests.cpp : : cfoa_conversion_operator_tests ;
173174

174175
local FCA_EXCEPTION_TESTS =
175176
constructor_exception_tests
Collapse file
+65Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// Copyright 2026 Braden Ganetsky
2+
// Distributed under the Boost Software License, Version 1.0.
3+
// https://www.boost.org/LICENSE_1_0.txt
4+
5+
#include <boost/static_assert.hpp>
6+
#include <boost/unordered/concurrent_flat_map.hpp>
7+
#include <boost/unordered/concurrent_flat_set.hpp>
8+
#include <boost/unordered/concurrent_node_map.hpp>
9+
#include <boost/unordered/concurrent_node_set.hpp>
10+
11+
using c_flat_map = boost::unordered::concurrent_flat_map<int, int>;
12+
using c_flat_set = boost::unordered::concurrent_flat_set<int>;
13+
using c_node_map = boost::unordered::concurrent_node_map<int, int>;
14+
using c_node_set = boost::unordered::concurrent_node_set<int>;
15+
16+
struct constrained_template_converter
17+
{
18+
struct dummy
19+
{
20+
};
21+
template <class T, typename std::enable_if<
22+
std::is_constructible<T, dummy>::value, int>::type = 0>
23+
operator T() const
24+
{
25+
return T{};
26+
}
27+
};
28+
29+
// Check whether the corresponding FOA container gets instantiated
30+
BOOST_STATIC_ASSERT(
31+
(!std::is_constructible<c_flat_map, constrained_template_converter>::value));
32+
BOOST_STATIC_ASSERT(
33+
(!std::is_constructible<c_flat_set, constrained_template_converter>::value));
34+
BOOST_STATIC_ASSERT(
35+
(!std::is_constructible<c_node_map, constrained_template_converter>::value));
36+
BOOST_STATIC_ASSERT(
37+
(!std::is_constructible<c_node_set, constrained_template_converter>::value));
38+
39+
#include <boost/unordered/unordered_flat_map.hpp>
40+
#include <boost/unordered/unordered_flat_set.hpp>
41+
#include <boost/unordered/unordered_node_map.hpp>
42+
#include <boost/unordered/unordered_node_set.hpp>
43+
44+
using flat_map = boost::unordered::unordered_flat_map<int, int>;
45+
using flat_set = boost::unordered::unordered_flat_set<int>;
46+
using node_map = boost::unordered::unordered_node_map<int, int>;
47+
using node_set = boost::unordered::unordered_node_set<int>;
48+
49+
template <class C> struct container_converter
50+
{
51+
operator C() const { return {}; }
52+
};
53+
54+
// Check whether the container can be constructed with an
55+
// implicit conversion to the corresponding FOA container
56+
BOOST_STATIC_ASSERT(
57+
(std::is_constructible<c_flat_map, container_converter<flat_map> >::value));
58+
BOOST_STATIC_ASSERT(
59+
(std::is_constructible<c_flat_set, container_converter<flat_set> >::value));
60+
BOOST_STATIC_ASSERT(
61+
(std::is_constructible<c_node_map, container_converter<node_map> >::value));
62+
BOOST_STATIC_ASSERT(
63+
(std::is_constructible<c_node_set, container_converter<node_set> >::value));
64+
65+
int main() { return 0; }

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.