Fix issue with constructing an FOA container from a class with a template conversion operator (#334)

* Add missing compile-only tests in CMake

* Rewrite the FOA containers' CFOA constructors so that a class with a template conversion operator does not instantiate the CFOA container

* Rewrite the CFOA containers' FOA constructors so that a class with a template conversion operator does not instantiate the FOA container
This commit is contained in:
Braden Ganetsky
2026-03-12 16:29:30 +01:00
committed by GitHub
parent 4fd90dc706
commit f1e2fa38b0
12 changed files with 132 additions and 18 deletions
+9
View File
@@ -163,4 +163,13 @@ cfoa_tests(SOURCES cfoa/rw_spinlock_test6.cpp)
cfoa_tests(SOURCES cfoa/rw_spinlock_test7.cpp)
cfoa_tests(SOURCES cfoa/rw_spinlock_test8.cpp)
# Compile tests
fca_tests(TYPE compile NAME explicit_instantiation_tests SOURCES unordered/explicit_instantiation_tests.cpp)
foa_tests(TYPE compile NAME explicit_instantiation_tests SOURCES unordered/explicit_instantiation_tests.cpp)
cfoa_tests(TYPE compile NAME explicit_instantiation_tests SOURCES cfoa/explicit_instantiation_tests.cpp)
foa_tests(TYPE compile NAME conversion_operator_tests SOURCES unordered/conversion_operator_tests.cpp)
cfoa_tests(TYPE compile NAME conversion_operator_tests SOURCES cfoa/conversion_operator_tests.cpp)
endif()
+3
View File
@@ -166,6 +166,9 @@ 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 ;
compile cfoa/conversion_operator_tests.cpp : : cfoa_conversion_operator_tests ;
local FCA_EXCEPTION_TESTS =
constructor_exception_tests
copy_exception_tests
+42
View File
@@ -0,0 +1,42 @@
// Copyright 2026 Braden Ganetsky
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/static_assert.hpp>
#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>
// Don't include the FOA headers here!
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>;
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 FOA container gets instantiated.
// The FOA headers aren't included, so this would fail to compile if the FOA
// container was instantiated.
BOOST_STATIC_ASSERT(
(!std::is_constructible<c_flat_map, constrained_template_converter>::value));
BOOST_STATIC_ASSERT(
(!std::is_constructible<c_flat_set, constrained_template_converter>::value));
BOOST_STATIC_ASSERT(
(!std::is_constructible<c_node_map, constrained_template_converter>::value));
BOOST_STATIC_ASSERT(
(!std::is_constructible<c_node_set, constrained_template_converter>::value));
int main() { return 0; }
@@ -0,0 +1,46 @@
// 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/static_assert.hpp>
#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>
// Don't include the CFOA headers here!
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.
// The CFOA headers aren't included, so this would fail to compile if the CFOA
// container was instantiated.
BOOST_STATIC_ASSERT(
(!std::is_constructible<flat_map, constrained_template_converter>::value));
BOOST_STATIC_ASSERT(
(!std::is_constructible<flat_set, constrained_template_converter>::value));
BOOST_STATIC_ASSERT(
(!std::is_constructible<node_map, constrained_template_converter>::value));
BOOST_STATIC_ASSERT(
(!std::is_constructible<node_set, constrained_template_converter>::value));
int main() { return 0; }