Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 25 additions & 4 deletions include/boost/unordered/unordered_flat_map.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Copyright (C) 2022-2023 Christian Mazakas
// Copyright (C) 2024-2025 Joaquin M Lopez Munoz
// Copyright (C) 2026 Braden Ganetsky
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

Expand Down Expand Up @@ -182,10 +183,30 @@ namespace boost {
{
}

template <bool avoid_explicit_instantiation = true>
unordered_flat_map(
concurrent_flat_map<Key, T, Hash, KeyEqual, Allocator>&& other)
: table_(std::move(other.table_))
template <class U,
typename std::enable_if<
// Ensure we match exactly `concurrent_flat_map&&`.
// Any lvalue references to `concurrent_flat_map` are not supported.
std::is_same<U,
concurrent_flat_map<Key, T, Hash, KeyEqual, Allocator> >::value,
int>::type = 0>
unordered_flat_map(U&& other) : table_(std::move(other.table_))
{
}

template <class U,
typename std::enable_if<
// Ensure we don't match any cvref-qualified `concurrent_flat_map&&`,
!detail::is_similar<U,
concurrent_flat_map<Key, T, Hash, KeyEqual, Allocator> >::value
// but we do match anything convertible to `concurrent_flat_map`.
&& std::is_convertible<U&&, concurrent_flat_map<Key, T, Hash,
KeyEqual, Allocator> >::value,
int>::type = 0>
unordered_flat_map(U&& other)
: unordered_flat_map(
concurrent_flat_map<Key, T, Hash, KeyEqual, Allocator>(
std::forward<U>(other)))
{
}

Expand Down
29 changes: 25 additions & 4 deletions include/boost/unordered/unordered_flat_set.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Copyright (C) 2022-2023 Christian Mazakas
// Copyright (C) 2024-2025 Joaquin M Lopez Munoz
// Copyright (C) 2026 Braden Ganetsky
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

Expand Down Expand Up @@ -178,10 +179,30 @@ namespace boost {
{
}

template <bool avoid_explicit_instantiation = true>
unordered_flat_set(
concurrent_flat_set<Key, Hash, KeyEqual, Allocator>&& other)
: table_(std::move(other.table_))
template <class U,
typename std::enable_if<
// Ensure we match exactly `concurrent_flat_set&&`.
// Any lvalue references to `concurrent_flat_set` are not supported.
std::is_same<U,
concurrent_flat_set<Key, Hash, KeyEqual, Allocator> >::value,
int>::type = 0>
unordered_flat_set(U&& other) : table_(std::move(other.table_))
{
}

template <class U,
typename std::enable_if<
// Ensure we don't match any cvref-qualified `concurrent_flat_set&&`,
!detail::is_similar<U,
concurrent_flat_set<Key, Hash, KeyEqual, Allocator> >::value
// but we do match anything convertible to `concurrent_flat_set`.
&& std::is_convertible<U&&,
concurrent_flat_set<Key, Hash, KeyEqual, Allocator> >::value,
int>::type = 0>
unordered_flat_set(U&& other)
: unordered_flat_set(
concurrent_flat_set<Key, Hash, KeyEqual, Allocator>(
std::forward<U>(other)))
{
}

Expand Down
29 changes: 25 additions & 4 deletions include/boost/unordered/unordered_node_map.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Copyright (C) 2022-2023 Christian Mazakas
// Copyright (C) 2024-2025 Joaquin M Lopez Munoz
// Copyright (C) 2026 Braden Ganetsky
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

Expand Down Expand Up @@ -189,10 +190,30 @@ namespace boost {
{
}

template <bool avoid_explicit_instantiation = true>
unordered_node_map(
concurrent_node_map<Key, T, Hash, KeyEqual, Allocator>&& other)
: table_(std::move(other.table_))
template <class U,
typename std::enable_if<
// Ensure we match exactly `concurrent_node_map&&`.
// Any lvalue references to `concurrent_node_map` are not supported.
std::is_same<U,
concurrent_node_map<Key, T, Hash, KeyEqual, Allocator> >::value,
int>::type = 0>
unordered_node_map(U&& other) : table_(std::move(other.table_))
{
}

template <class U,
typename std::enable_if<
// Ensure we don't match any cvref-qualified `concurrent_node_map&&`,
!detail::is_similar<U,
concurrent_node_map<Key, T, Hash, KeyEqual, Allocator> >::value
// but we do match anything convertible to `concurrent_node_map`.
&& std::is_convertible<U&&, concurrent_node_map<Key, T, Hash,
KeyEqual, Allocator> >::value,
int>::type = 0>
unordered_node_map(U&& other)
: unordered_node_map(
concurrent_node_map<Key, T, Hash, KeyEqual, Allocator>(
std::forward<U>(other)))
{
}

Expand Down
29 changes: 25 additions & 4 deletions include/boost/unordered/unordered_node_set.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Copyright (C) 2022-2023 Christian Mazakas
// Copyright (C) 2024-2025 Joaquin M Lopez Munoz
// Copyright (C) 2026 Braden Ganetsky
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

Expand Down Expand Up @@ -187,10 +188,30 @@ namespace boost {
{
}

template <bool avoid_explicit_instantiation = true>
unordered_node_set(
concurrent_node_set<Key, Hash, KeyEqual, Allocator>&& other)
: table_(std::move(other.table_))
template <class U,
typename std::enable_if<
// Ensure we match exactly `concurrent_node_set&&`.
// Any lvalue references to `concurrent_node_set` are not supported.
std::is_same<U,
concurrent_node_set<Key, Hash, KeyEqual, Allocator> >::value,
int>::type = 0>
unordered_node_set(U&& other) : table_(std::move(other.table_))
{
}

template <class U,
typename std::enable_if<
// Ensure we don't match any cvref-qualified `concurrent_node_set&&`,
!detail::is_similar<U,
concurrent_node_set<Key, Hash, KeyEqual, Allocator> >::value
// but we do match anything convertible to `concurrent_node_set`.
&& std::is_convertible<U&&,
concurrent_node_set<Key, Hash, KeyEqual, Allocator> >::value,
int>::type = 0>
unordered_node_set(U&& other)
: unordered_node_set(
concurrent_node_set<Key, Hash, KeyEqual, Allocator>(
std::forward<U>(other)))
{
}

Expand Down
6 changes: 6 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ fca_tests(TYPE compile-fail NAME insert_node_type_fail_multimap COMPILE_DEFINITI
fca_tests(TYPE compile-fail NAME insert_node_type_fail_set COMPILE_DEFINITIONS UNORDERED_TEST_SET SOURCES unordered/insert_node_type_fail.cpp)
fca_tests(TYPE compile-fail NAME insert_node_type_fail_multiset COMPILE_DEFINITIONS UNORDERED_TEST_MULTISET SOURCES unordered/insert_node_type_fail.cpp)

fca_tests(TYPE compile NAME fca_explicit_instantiation_tests SOURCES unordered/explicit_instantiation_tests.cpp)
fca_tests(TYPE compile NAME foa_explicit_instantiation_tests COMPILE_DEFINITIONS BOOST_UNORDERED_FOA_TESTS SOURCES unordered/explicit_instantiation_tests.cpp)
fca_tests(TYPE compile NAME cfoa_explicit_instantiation_tests SOURCES cfoa/explicit_instantiation_tests.cpp)

fca_tests(TYPE compile NAME foa_conversion_operator_tests COMPILE_DEFINITIONS BOOST_UNORDERED_FOA_TESTS SOURCES unordered/conversion_operator_tests.cpp)

# FOA tests

foa_tests(SOURCES unordered/fwd_set_test.cpp)
Expand Down
2 changes: 2 additions & 0 deletions test/Jamfile.v2
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@ compile unordered/explicit_instantiation_tests.cpp :
compile unordered/explicit_instantiation_tests.cpp : <define>BOOST_UNORDERED_FOA_TESTS : foa_explicit_instantiation_tests ;
compile cfoa/explicit_instantiation_tests.cpp : : cfoa_explicit_instantiation_tests ;

compile unordered/conversion_operator_tests.cpp : <define>BOOST_UNORDERED_FOA_TESTS : foa_conversion_operator_tests ;

local FCA_EXCEPTION_TESTS =
constructor_exception_tests
copy_exception_tests
Expand Down
68 changes: 68 additions & 0 deletions test/unordered/conversion_operator_tests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright 2026 Braden Ganetsky
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt

#if !defined(BOOST_UNORDERED_FOA_TESTS)
#error "This test is only for the FOA-style conatiners"
#endif

#include <boost/unordered/unordered_flat_map.hpp>
#include <boost/unordered/unordered_flat_set.hpp>
#include <boost/unordered/unordered_node_map.hpp>
#include <boost/unordered/unordered_node_set.hpp>

using flat_map = boost::unordered::unordered_flat_map<int, int>;
using flat_set = boost::unordered::unordered_flat_set<int>;
using node_map = boost::unordered::unordered_node_map<int, int>;
using node_set = boost::unordered::unordered_node_set<int>;

struct constrained_template_converter
{
struct dummy
{
};
template <class T, typename std::enable_if<
std::is_constructible<T, dummy>::value, int>::type = 0>
operator T() const
{
return T{};
}
};

// Check whether the corresponding CFOA container gets instantiated
static_assert(
!std::is_constructible<flat_map, constrained_template_converter>::value);
static_assert(
!std::is_constructible<flat_set, constrained_template_converter>::value);
static_assert(
!std::is_constructible<node_map, constrained_template_converter>::value);
static_assert(
!std::is_constructible<node_set, constrained_template_converter>::value);

#include <boost/unordered/concurrent_flat_map.hpp>
#include <boost/unordered/concurrent_flat_set.hpp>
#include <boost/unordered/concurrent_node_map.hpp>
#include <boost/unordered/concurrent_node_set.hpp>

using c_flat_map = boost::unordered::concurrent_flat_map<int, int>;
using c_flat_set = boost::unordered::concurrent_flat_set<int>;
using c_node_map = boost::unordered::concurrent_node_map<int, int>;
using c_node_set = boost::unordered::concurrent_node_set<int>;

template <class C> struct container_converter
{
operator C() const { return {}; }
};

// Check whether the container can be constructed with an
// implicit conversion to the corresponding CFOA container
static_assert(
std::is_constructible<flat_map, container_converter<c_flat_map> >::value);
static_assert(
std::is_constructible<flat_set, container_converter<c_flat_set> >::value);
static_assert(
std::is_constructible<node_map, container_converter<c_node_map> >::value);
static_assert(
std::is_constructible<node_set, container_converter<c_node_set> >::value);

int main() { return 0; }
Loading