mirror of
https://github.com/ETLCPP/etl.git
synced 2026-10-28 18:07:10 +08:00
Constrain variant value constructor to supported types (#1614)
* Add docs and tutorial for etl::intrusive_avl_tree (#1608) * Add docs and tutorial for etl::intrusive_avl_tree Documents the intrusive AVL tree added in PR #1425: a full API reference page under Containers/Trees, and a tutorial demonstrating ordered access to intrusively-linked objects with unpredictable lifetimes, including move support and destructor-driven automatic removal from the tree. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Add complexity shortcode and document its usage Introduces a {{< complexity >}} Hugo shortcode (with light/dark styling for constant/logarithmic/linear/linearithmic/polynomial/exponential classes) for rendering Big-O complexity inline, applies it throughout the intrusive_avl_tree API reference in place of raw "O(...)" text, and documents the Description/Complexity structure and supported classes in DOCUMENTATION.md. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Fix issues found by @CodeRabbit * Put complexity notes on their own lines in intrusive_avl_tree docs Move the complexity shortcode from the inline "**Complexity:**" label to its own line under a "**Complexity**" label. Notes that give several alternatives (e.g. amortized vs. worst-case) now show each one on a separate line. Update the guideline in DOCUMENTATION.md to match. * Update complexity examples in DOCUMENTATION.md Add the hard line break after the "**Complexity**" label in the example, and rewrite the list of supported complexity classes in the new two-line format, including an example with several alternatives. * Add logarithmic complexity example to DOCUMENTATION.md --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com> Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com> * Updated sponsors pages * Refactor the documentation css to group styles for light and dark themes * Update Codacy badge in README.md Updated Codacy badge link to reflect new project status. * Fix Codacy badge display * Constrain variant value constructor to supported types Previously, the implicit value constructor of etl::variant could participate in overload resolution for unsupported types, potentially causing ambiguous calls before the assertion was triggered. The static_assert are replaced by enable_if constraints. Note the same approach is applied to other constructors and methods for consistency. --------- Co-authored-by: Sergei <sergej.shirokov@gmail.com> Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com> Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com> Co-authored-by: John Wellbelove <john.wellbelove@etlcpp.com>
This commit is contained in:
parent
5fe4a6cbd0
commit
5635a7ab26
@ -1023,22 +1023,23 @@ namespace etl
|
||||
/// Construct from a value.
|
||||
//***************************************************************************
|
||||
#include "diagnostic_uninitialized_push.h"
|
||||
template <typename T, bool Trivial_ = Is_Trivially_Destructible_Suite,
|
||||
etl::enable_if_t<!etl::is_same<etl::remove_cvref_t<T>, variant>::value && !Trivial_, int> = 0>
|
||||
template <
|
||||
typename T, bool Trivial_ = Is_Trivially_Destructible_Suite,
|
||||
etl::enable_if_t<!etl::is_same<etl::remove_cvref_t<T>, variant>::value && !Trivial_ && etl::is_one_of<etl::remove_cvref_t<T>, TTypes...>::value,
|
||||
int> = 0>
|
||||
ETL_CONSTEXPR14 variant(T&& value)
|
||||
: base_type(index_of_type<T>::value)
|
||||
{
|
||||
static_assert(etl::is_one_of<etl::remove_cvref_t<T>, TTypes...>::value, "Unsupported type");
|
||||
|
||||
construct_in_place<etl::remove_cvref_t<T> >(data, etl::forward<T>(value));
|
||||
}
|
||||
|
||||
template <typename T, bool Trivial_ = Is_Trivially_Destructible_Suite,
|
||||
etl::enable_if_t<!etl::is_same<etl::remove_cvref_t<T>, variant>::value && Trivial_, int> = 0>
|
||||
template <
|
||||
typename T, bool Trivial_ = Is_Trivially_Destructible_Suite,
|
||||
etl::enable_if_t<!etl::is_same<etl::remove_cvref_t<T>, variant>::value && Trivial_ && etl::is_one_of<etl::remove_cvref_t<T>, TTypes...>::value,
|
||||
int> = 0>
|
||||
constexpr variant(T&& value)
|
||||
: base_type(etl::in_place_index_t<index_of_type<T>::value>{}, etl::forward<T>(value), index_of_type<T>::value)
|
||||
{
|
||||
static_assert(etl::is_one_of<etl::remove_cvref_t<T>, TTypes...>::value, "Unsupported type");
|
||||
}
|
||||
#include "diagnostic_pop.h"
|
||||
|
||||
@ -1056,20 +1057,19 @@ namespace etl
|
||||
/// Construct from arguments.
|
||||
//***************************************************************************
|
||||
#include "diagnostic_uninitialized_push.h"
|
||||
template <typename T, typename... TArgs, bool Trivial_ = Is_Trivially_Destructible_Suite, etl::enable_if_t<!Trivial_, int> = 0>
|
||||
template <typename T, typename... TArgs, bool Trivial_ = Is_Trivially_Destructible_Suite,
|
||||
etl::enable_if_t<!Trivial_ && etl::is_one_of<etl::remove_cvref_t<T>, TTypes...>::value, int> = 0>
|
||||
ETL_CONSTEXPR14 explicit variant(etl::in_place_type_t<T>, TArgs&&... args)
|
||||
: base_type(index_of_type<T>::value)
|
||||
{
|
||||
static_assert(etl::is_one_of<etl::remove_cvref_t<T>, TTypes...>::value, "Unsupported type");
|
||||
|
||||
construct_in_place_args<etl::remove_cvref_t<T> >(data, etl::forward<TArgs>(args)...);
|
||||
}
|
||||
|
||||
template <typename T, typename... TArgs, bool Trivial_ = Is_Trivially_Destructible_Suite, etl::enable_if_t<Trivial_, int> = 0>
|
||||
template <typename T, typename... TArgs, bool Trivial_ = Is_Trivially_Destructible_Suite,
|
||||
etl::enable_if_t<Trivial_ && etl::is_one_of<etl::remove_cvref_t<T>, TTypes...>::value, int> = 0>
|
||||
constexpr explicit variant(etl::in_place_type_t<T>, TArgs&&... args)
|
||||
: base_type(etl::in_place_index_t<index_of_type<T>::value>{}, etl::remove_cvref_t<T>(etl::forward<TArgs>(args)...), index_of_type<T>::value)
|
||||
{
|
||||
static_assert(etl::is_one_of<etl::remove_cvref_t<T>, TTypes...>::value, "Unsupported type");
|
||||
}
|
||||
#include "diagnostic_pop.h"
|
||||
|
||||
@ -1077,22 +1077,20 @@ namespace etl
|
||||
/// Construct from arguments.
|
||||
//***************************************************************************
|
||||
#include "diagnostic_uninitialized_push.h"
|
||||
template <size_t Index, typename... TArgs, bool Trivial_ = Is_Trivially_Destructible_Suite, etl::enable_if_t<!Trivial_, int> = 0>
|
||||
template <size_t Index, typename... TArgs, bool Trivial_ = Is_Trivially_Destructible_Suite,
|
||||
etl::enable_if_t<!Trivial_ && (Index < sizeof...(TTypes)), int> = 0>
|
||||
ETL_CONSTEXPR14 explicit variant(etl::in_place_index_t<Index>, TArgs&&... args)
|
||||
: base_type(Index)
|
||||
{
|
||||
using type = type_from_index<Index>;
|
||||
static_assert(etl::is_one_of<type, TTypes...>::value, "Unsupported type");
|
||||
|
||||
construct_in_place_args<type>(data, etl::forward<TArgs>(args)...);
|
||||
}
|
||||
|
||||
template <size_t Index, typename... TArgs, bool Trivial_ = Is_Trivially_Destructible_Suite, etl::enable_if_t<Trivial_, int> = 0>
|
||||
template <size_t Index, typename... TArgs, bool Trivial_ = Is_Trivially_Destructible_Suite,
|
||||
etl::enable_if_t<Trivial_ && (Index < sizeof...(TTypes)), int> = 0>
|
||||
constexpr explicit variant(etl::in_place_index_t<Index>, TArgs&&... args)
|
||||
: base_type(etl::in_place_index_t<Index>{}, type_from_index<Index>(etl::forward<TArgs>(args)...), Index)
|
||||
{
|
||||
using type = type_from_index<Index>;
|
||||
static_assert(etl::is_one_of<type, TTypes...>::value, "Unsupported type");
|
||||
}
|
||||
#include "diagnostic_pop.h"
|
||||
|
||||
@ -1101,12 +1099,10 @@ namespace etl
|
||||
/// Construct from type, initializer_list and arguments.
|
||||
//***************************************************************************
|
||||
#include "diagnostic_uninitialized_push.h"
|
||||
template <typename T, typename U, typename... TArgs >
|
||||
template <typename T, typename U, typename... TArgs, etl::enable_if_t<etl::is_one_of<etl::remove_cvref_t<T>, TTypes...>::value, int> = 0>
|
||||
ETL_CONSTEXPR14 explicit variant(etl::in_place_type_t<T>, std::initializer_list<U> init, TArgs&&... args)
|
||||
: base_type(index_of_type<T>::value)
|
||||
{
|
||||
static_assert(etl::is_one_of<etl::remove_cvref_t<T>, TTypes...>::value, "Unsupported type");
|
||||
|
||||
construct_in_place_args<etl::remove_cvref_t<T> >(data, init, etl::forward<TArgs>(args)...);
|
||||
}
|
||||
#include "diagnostic_pop.h"
|
||||
@ -1115,13 +1111,11 @@ namespace etl
|
||||
/// Construct from index, initializer_list and arguments.
|
||||
//***************************************************************************
|
||||
#include "diagnostic_uninitialized_push.h"
|
||||
template <size_t Index, typename U, typename... TArgs >
|
||||
template <size_t Index, typename U, typename... TArgs, etl::enable_if_t<(Index < sizeof...(TTypes)), int> = 0>
|
||||
ETL_CONSTEXPR14 explicit variant(etl::in_place_index_t<Index>, std::initializer_list<U> init, TArgs&&... args)
|
||||
: base_type(Index)
|
||||
{
|
||||
using type = type_from_index<Index>;
|
||||
static_assert(etl::is_one_of<type, TTypes...>::value, "Unsupported type");
|
||||
|
||||
construct_in_place_args<type>(data, init, etl::forward<TArgs>(args)...);
|
||||
}
|
||||
#include "diagnostic_pop.h"
|
||||
@ -1149,11 +1143,9 @@ namespace etl
|
||||
//***************************************************************************
|
||||
/// Emplace by type with variadic constructor parameters.
|
||||
//***************************************************************************
|
||||
template <typename T, typename... TArgs>
|
||||
template <typename T, typename... TArgs, etl::enable_if_t<etl::is_one_of<T, TTypes...>::value, int> = 0>
|
||||
T& emplace(TArgs&&... args) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<etl::remove_cvref_t<T>, TArgs...>::value))
|
||||
{
|
||||
static_assert(etl::is_one_of<T, TTypes...>::value, "Unsupported type");
|
||||
|
||||
using type = etl::remove_cvref_t<T>;
|
||||
|
||||
do_destroy();
|
||||
@ -1168,12 +1160,10 @@ namespace etl
|
||||
//***************************************************************************
|
||||
/// Emplace by type with variadic constructor parameters.
|
||||
//***************************************************************************
|
||||
template <typename T, typename U, typename... TArgs>
|
||||
template <typename T, typename U, typename... TArgs, etl::enable_if_t<etl::is_one_of<T, TTypes...>::value, int> = 0>
|
||||
T& emplace(std::initializer_list<U> il, TArgs&&... args)
|
||||
ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<etl::remove_cvref_t<T>, std::initializer_list<U>, TArgs...>::value))
|
||||
{
|
||||
static_assert(etl::is_one_of<T, TTypes...>::value, "Unsupported type");
|
||||
|
||||
using type = etl::remove_cvref_t<T>;
|
||||
|
||||
do_destroy();
|
||||
@ -1188,12 +1178,10 @@ namespace etl
|
||||
//***************************************************************************
|
||||
/// Emplace by index with variadic constructor parameters.
|
||||
//***************************************************************************
|
||||
template <size_t Index, typename... TArgs>
|
||||
template <size_t Index, typename... TArgs, etl::enable_if_t<(Index < sizeof...(TTypes)), int> = 0>
|
||||
typename etl::variant_alternative_t<Index, variant<TTypes...> >& emplace(TArgs&&... args)
|
||||
ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<type_from_index<Index>, TArgs...>::value))
|
||||
{
|
||||
static_assert(Index < sizeof...(TTypes), "Index out of range");
|
||||
|
||||
using type = type_from_index<Index>;
|
||||
|
||||
do_destroy();
|
||||
@ -1208,12 +1196,10 @@ namespace etl
|
||||
//***************************************************************************
|
||||
/// Emplace by index with variadic constructor parameters.
|
||||
//***************************************************************************
|
||||
template <size_t Index, typename U, typename... TArgs>
|
||||
template <size_t Index, typename U, typename... TArgs, etl::enable_if_t<(Index < sizeof...(TTypes)), int> = 0>
|
||||
typename etl::variant_alternative_t<Index, variant<TTypes...> >& emplace(std::initializer_list<U> il, TArgs&&... args)
|
||||
ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<type_from_index<Index>, std::initializer_list<U>, TArgs...>::value))
|
||||
{
|
||||
static_assert(Index < sizeof...(TTypes), "Index out of range");
|
||||
|
||||
using type = type_from_index<Index>;
|
||||
|
||||
do_destroy();
|
||||
@ -1229,13 +1215,13 @@ namespace etl
|
||||
/// Move assignment operator for type.
|
||||
///\param value The value to assign.
|
||||
//***************************************************************************
|
||||
template <typename T, etl::enable_if_t<!etl::is_same<etl::remove_cvref_t<T>, variant>::value, int> = 0>
|
||||
template <
|
||||
typename T,
|
||||
etl::enable_if_t<!etl::is_same<etl::remove_cvref_t<T>, variant>::value && etl::is_one_of<etl::remove_cvref_t<T>, TTypes...>::value, int> = 0>
|
||||
variant& operator=(T&& value)
|
||||
{
|
||||
using type = etl::remove_cvref_t<T>;
|
||||
|
||||
static_assert(etl::is_one_of<type, TTypes...>::value, "Unsupported type");
|
||||
|
||||
do_destroy();
|
||||
do_construct<type>(etl::forward<T>(value));
|
||||
|
||||
|
||||
@ -2932,6 +2932,21 @@ namespace
|
||||
CHECK(etl::get_if<int>(&v1) != nullptr);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_variant_implicit_conversion_constraints)
|
||||
{
|
||||
struct overloaded
|
||||
{
|
||||
overloaded(etl::variant<char, int>&&) {}
|
||||
overloaded(etl::variant<float, NonTrivialNonMovable>&&) {}
|
||||
};
|
||||
|
||||
/* Construct from value, trivially destructible suite */
|
||||
overloaded(1);
|
||||
/* Construct from value, non-trivially destructible suite */
|
||||
overloaded(1.0f);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
// Tests for noexcept properties of etl::variant
|
||||
// The noexcept specs only take effect when ETL_USING_EXCEPTIONS is enabled,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user