LCOV - code coverage report
Current view: top level - small_vector - small_vector.h (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 91 105 86.7 %
Date: 2024-10-18 14:00:25 Functions: 31 43 72.1 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :  * An implementation of `small_vector` (a vector with a small
       3             :  * buffer optimization). I would probably have preferred to
       4             :  * call this `inline_vector`, but I'll just go with the canonical
       5             :  * name for now.
       6             :  *
       7             :  * Copyright © 2020-2021 Gene Harvey
       8             :  *
       9             :  * This software may be modified and distributed under the terms
      10             :  * of the MIT license. See the LICENSE file for details.
      11             : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
      12             : #ifndef __PLUMED_small_vector_small_vector_h
      13             : #define __PLUMED_small_vector_small_vector_h
      14             : /** small_vector.hpp
      15             :  * An implementation of `small_vector` (a vector with a small
      16             :  * buffer optimization). I would probably have preferred to
      17             :  * call this `inline_vector`, but I'll just go with the canonical
      18             :  * name for now.
      19             :  *
      20             :  * Copyright © 2020-2021 Gene Harvey
      21             :  *
      22             :  * This software may be modified and distributed under the terms
      23             :  * of the MIT license. See the LICENSE file for details.
      24             :  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
      25             : 
      26             : #ifndef PLUMED_GCH_SMALL_VECTOR_HPP
      27             : #define PLUMED_GCH_SMALL_VECTOR_HPP
      28             : 
      29             : #ifdef __clang__
      30             : #  ifndef PLUMED_GCH_CLANG
      31             : #    define PLUMED_GCH_CLANG
      32             : #  endif
      33             : #  if defined (__cplusplus) && __cplusplus >= 201103L
      34             : #    ifndef PLUMED_GCH_CLANG_11
      35             : #      define PLUMED_GCH_CLANG_11
      36             : #    endif
      37             : #  endif
      38             : #  if defined (__cplusplus) && __cplusplus >= 201402L
      39             : #    ifndef PLUMED_GCH_CLANG_14
      40             : #      define PLUMED_GCH_CLANG_14
      41             : #    endif
      42             : #  endif
      43             : #  if defined (__cplusplus) && __cplusplus >= 201703L
      44             : #    ifndef PLUMED_GCH_CLANG_17
      45             : #      define PLUMED_GCH_CLANG_17
      46             : #    endif
      47             : #  endif
      48             : #  if defined (__cplusplus) && __cplusplus >= 202002L
      49             : #    ifndef PLUMED_GCH_CLANG_20
      50             : #      define PLUMED_GCH_CLANG_20
      51             : #    endif
      52             : #  endif
      53             : #endif
      54             : 
      55             : #ifndef PLUMED_GCH_CPP14_CONSTEXPR
      56             : #  if defined (__cpp_constexpr) && __cpp_constexpr >= 201304L
      57             : #    define PLUMED_GCH_CPP14_CONSTEXPR constexpr
      58             : #    ifndef PLUMED_GCH_HAS_CPP14_CONSTEXPR
      59             : #      define PLUMED_GCH_HAS_CPP14_CONSTEXPR
      60             : #    endif
      61             : #  else
      62             : #    define PLUMED_GCH_CPP14_CONSTEXPR
      63             : #  endif
      64             : #endif
      65             : 
      66             : #ifndef PLUMED_GCH_CPP17_CONSTEXPR
      67             : #  if defined (__cpp_constexpr) && __cpp_constexpr >= 201603L
      68             : #    define PLUMED_GCH_CPP17_CONSTEXPR constexpr
      69             : #    ifndef PLUMED_GCH_HAS_CPP17_CONSTEXPR
      70             : #      define PLUMED_GCH_HAS_CPP17_CONSTEXPR
      71             : #    endif
      72             : #  else
      73             : #    define PLUMED_GCH_CPP17_CONSTEXPR
      74             : #  endif
      75             : #endif
      76             : 
      77             : #ifndef PLUMED_GCH_CPP20_CONSTEXPR
      78             : #  if defined (__cpp_constexpr) && __cpp_constexpr >= 201907L
      79             : #    define PLUMED_GCH_CPP20_CONSTEXPR constexpr
      80             : #    ifndef PLUMED_GCH_HAS_CPP20_CONSTEXPR
      81             : #      define PLUMED_GCH_HAS_CPP20_CONSTEXPR
      82             : #    endif
      83             : #  else
      84             : #    define PLUMED_GCH_CPP20_CONSTEXPR
      85             : #  endif
      86             : #endif
      87             : 
      88             : #ifndef PLUMED_GCH_NORETURN
      89             : #  if defined (__has_cpp_attribute) && __has_cpp_attribute (noreturn) >= 200809L
      90             : #    define PLUMED_GCH_NORETURN [[noreturn]]
      91             : #  else
      92             : #    define PLUMED_GCH_NORETURN
      93             : #  endif
      94             : #endif
      95             : 
      96             : #ifndef PLUMED_GCH_NODISCARD
      97             : #  if defined (__has_cpp_attribute) && __has_cpp_attribute (nodiscard) >= 201603L
      98             : #    if ! defined (__clang__) || defined (PLUMED_GCH_CLANG_17)
      99             : #      define PLUMED_GCH_NODISCARD [[nodiscard]]
     100             : #    else
     101             : #      define PLUMED_GCH_NODISCARD
     102             : #    endif
     103             : #  else
     104             : #    define PLUMED_GCH_NODISCARD
     105             : #  endif
     106             : #endif
     107             : 
     108             : #ifndef PLUMED_GCH_INLINE_VARIABLE
     109             : #  if defined (__cpp_inline_variables) && __cpp_inline_variables >= 201606L
     110             : #    define PLUMED_GCH_INLINE_VARIABLE inline
     111             : #  else
     112             : #    define PLUMED_GCH_INLINE_VARIABLE
     113             : #  endif
     114             : #endif
     115             : 
     116             : #ifndef PLUMED_GCH_EMPTY_BASE
     117             : #  if defined (_MSC_FULL_VER) && _MSC_FULL_VER >= 190023918L
     118             : #    define PLUMED_GCH_EMPTY_BASE __declspec (empty_bases)
     119             : #  else
     120             : #    define PLUMED_GCH_EMPTY_BASE
     121             : #  endif
     122             : #endif
     123             : 
     124             : #ifndef PLUMED_GCH_IMPLICIT_CONVERSION
     125             : #  if defined (__cpp_conditional_explicit) && __cpp_conditional_explicit >= 201806L
     126             : #    define PLUMED_GCH_IMPLICIT_CONVERSION explicit (false)
     127             : #  else
     128             : #    define PLUMED_GCH_IMPLICIT_CONVERSION /* implicit */
     129             : #  endif
     130             : #endif
     131             : 
     132             : #if defined (__cpp_variable_templates) && __cpp_variable_templates >= 201304L
     133             : #  ifndef PLUMED_GCH_VARIABLE_TEMPLATES
     134             : #    define PLUMED_GCH_VARIABLE_TEMPLATES
     135             : #  endif
     136             : #endif
     137             : 
     138             : #if defined (__cpp_deduction_guides) && __cpp_deduction_guides >= 201703L
     139             : #  ifndef PLUMED_GCH_CTAD_SUPPORT
     140             : #    define PLUMED_GCH_CTAD_SUPPORT
     141             : #  endif
     142             : #endif
     143             : 
     144             : #if defined (__cpp_if_constexpr) && __cpp_if_constexpr >= 201606L
     145             : #  ifndef PLUMED_GCH_CONSTEXPR_IF
     146             : #    define PLUMED_GCH_CONSTEXPR_IF
     147             : #  endif
     148             : #endif
     149             : 
     150             : #if defined (__cpp_exceptions) && __cpp_exceptions >= 199711L
     151             : #  ifndef PLUMED_GCH_EXCEPTIONS
     152             : #    define PLUMED_GCH_EXCEPTIONS
     153             : #  endif
     154             : #endif
     155             : 
     156             : #ifndef PLUMED_GCH_TRY
     157             : #  ifdef PLUMED_GCH_EXCEPTIONS
     158             : #    define PLUMED_GCH_TRY try
     159             : #  else
     160             : #    ifdef PLUMED_GCH_CONSTEXPR_IF
     161             : #      define PLUMED_GCH_TRY if constexpr (true)
     162             : #    else
     163             : #      define PLUMED_GCH_TRY if (true)
     164             : #    endif
     165             : #  endif
     166             : #endif
     167             : 
     168             : #ifndef PLUMED_GCH_CATCH
     169             : #  ifdef PLUMED_GCH_EXCEPTIONS
     170             : #    define PLUMED_GCH_CATCH(...) catch (__VA_ARGS__)
     171             : #  else
     172             : #    ifdef PLUMED_GCH_CONSTEXPR_IF
     173             : #      define PLUMED_GCH_CATCH(...) else if constexpr (false)
     174             : #    else
     175             : #      define PLUMED_GCH_CATCH(...) else if (false)
     176             : #    endif
     177             : #  endif
     178             : #endif
     179             : 
     180             : #ifndef PLUMED_GCH_THROW
     181             : #  ifdef PLUMED_GCH_EXCEPTIONS
     182             : #    define PLUMED_GCH_THROW throw
     183             : #  else
     184             : #    define PLUMED_GCH_THROW
     185             : #  endif
     186             : #endif
     187             : 
     188             : #ifndef PLUMED_GCH_CONSTEVAL
     189             : #  if defined (__cpp_consteval) && __cpp_consteval >= 201811L
     190             : #    define PLUMED_GCH_CONSTEVAL consteval
     191             : #    ifndef PLUMED_GCH_HAS_CONSTEVAL
     192             : #      define PLUMED_GCH_HAS_CONSTEVAL
     193             : #    endif
     194             : #  else
     195             : #    define PLUMED_GCH_CONSTEVAL constexpr
     196             : #  endif
     197             : #endif
     198             : 
     199             : #if defined (__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L
     200             : #  ifndef PLUMED_GCH_IMPL_THREE_WAY_COMPARISON
     201             : #    define PLUMED_GCH_IMPL_THREE_WAY_COMPARISON
     202             : #  endif
     203             : #endif
     204             : 
     205             : #if defined (__cpp_concepts) && __cpp_concepts >= 201907L
     206             : #  ifndef PLUMED_GCH_CONCEPTS
     207             : #    define PLUMED_GCH_CONCEPTS
     208             : #  endif
     209             : #endif
     210             : 
     211             : #include <algorithm>
     212             : #include <cassert>
     213             : #include <cstddef>
     214             : #include <cstdint>
     215             : #include <cstring>
     216             : #include <initializer_list>
     217             : #include <iterator>
     218             : #include <limits>
     219             : #include <memory>
     220             : #include <new>
     221             : #include <type_traits>
     222             : #include <utility>
     223             : 
     224             : #ifdef PLUMED_GCH_IMPL_THREE_WAY_COMPARISON
     225             : #  if defined (__has_include) && __has_include (<compare>)
     226             : #    include <compare>
     227             : #  endif
     228             : #endif
     229             : 
     230             : #ifdef PLUMED_GCH_CONCEPTS
     231             : #  if defined (__has_include) && __has_include (<concepts>)
     232             : #    include <concepts>
     233             : #  endif
     234             : #endif
     235             : 
     236             : #ifdef PLUMED_GCH_STDLIB_INTEROP
     237             : #  include <array>
     238             : #  include <valarray>
     239             : #  include <vector>
     240             : #endif
     241             : 
     242             : #ifdef PLUMED_GCH_EXCEPTIONS
     243             : #  include <stdexcept>
     244             : #else
     245             : #  include <cstdio>
     246             : #  include <cstdlib>
     247             : #endif
     248             : 
     249             : #if defined (__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L
     250             : #  ifndef PLUMED_GCH_LIB_THREE_WAY_COMPARISON
     251             : #    define PLUMED_GCH_LIB_THREE_WAY_COMPARISON
     252             : #  endif
     253             : #endif
     254             : 
     255             : #if defined (__cpp_lib_concepts) && __cpp_lib_concepts >= 202002L
     256             : #  if ! defined (PLUMED_GCH_LIB_CONCEPTS) && ! defined (PLUMED_GCH_DISABLE_CONCEPTS)
     257             : #    define PLUMED_GCH_LIB_CONCEPTS
     258             : #  endif
     259             : #endif
     260             : 
     261             : #if defined (__cpp_lib_is_final) && __cpp_lib_is_final >= 201402L
     262             : #  ifndef PLUMED_GCH_LIB_IS_FINAL
     263             : #    define PLUMED_GCH_LIB_IS_FINAL
     264             : #  endif
     265             : #endif
     266             : 
     267             : #if defined (__cpp_lib_is_constant_evaluated) && __cpp_lib_is_constant_evaluated >= 201811L
     268             : #  ifndef PLUMED_GCH_LIB_IS_CONSTANT_EVALUATED
     269             : #    define PLUMED_GCH_LIB_IS_CONSTANT_EVALUATED
     270             : #  endif
     271             : #endif
     272             : 
     273             : #if defined (__cpp_lib_is_swappable) && __cpp_lib_is_swappable >= 201603L
     274             : #  ifndef PLUMED_GCH_LIB_IS_SWAPPABLE
     275             : #    define PLUMED_GCH_LIB_IS_SWAPPABLE
     276             : #  endif
     277             : #endif
     278             : 
     279             : #if defined (__cpp_lib_allocator_traits_is_always_equal)
     280             : #  if __cpp_lib_allocator_traits_is_always_equal >= 201411L
     281             : #    ifndef PLUMED_GCH_LIB_IS_ALWAYS_EQUAL
     282             : #      define PLUMED_GCH_LIB_IS_ALWAYS_EQUAL
     283             : #    endif
     284             : #  endif
     285             : #endif
     286             : 
     287             : #if defined (__cpp_lib_constexpr_memory) && __cpp_lib_constexpr_memory >= 201811L
     288             : #  ifndef PLUMED_GCH_LIB_CONSTEXPR_MEMORY
     289             : #    define PLUMED_GCH_LIB_CONSTEXPR_MEMORY
     290             : #  endif
     291             : #endif
     292             : 
     293             : // TODO:
     294             : //   Make sure we don't need any laundering in the internal class functions.
     295             : //   I also need some sort of test case to actually show where UB is occurring,
     296             : //   because it's still a bit unclear to me.
     297             : #if defined (__cpp_lib_launder) && __cpp_lib_launder >= 201606L
     298             : #  ifndef PLUMED_GCH_LIB_LAUNDER
     299             : #    define PLUMED_GCH_LIB_LAUNDER
     300             : #  endif
     301             : #endif
     302             : 
     303             : // defined if the entire thing is available for constexpr
     304             : #ifndef PLUMED_GCH_SMALL_VECTOR_CONSTEXPR
     305             : #  if defined (PLUMED_GCH_HAS_CPP20_CONSTEXPR) && defined (PLUMED_GCH_LIB_IS_CONSTANT_EVALUATED) \
     306             :                                         && defined (PLUMED_GCH_LIB_CONSTEXPR_MEMORY)
     307             : #    define PLUMED_GCH_SMALL_VECTOR_CONSTEXPR constexpr
     308             : #    ifndef PLUMED_GCH_HAS_CONSTEXPR_SMALL_VECTOR
     309             : #      define PLUMED_GCH_HAS_CONSTEXPR_SMALL_VECTOR
     310             : #    endif
     311             : #  else
     312             : #    define PLUMED_GCH_SMALL_VECTOR_CONSTEXPR
     313             : #  endif
     314             : #endif
     315             : 
     316             : #ifndef PLUMED_GCH_SMALL_VECTOR_DEFAULT_SIZE
     317             : #  define PLUMED_GCH_SMALL_VECTOR_DEFAULT_SIZE 64
     318             : #endif
     319             : 
     320             : namespace PLMD {
     321             : namespace gch
     322             : {
     323             : 
     324             : #ifdef PLUMED_GCH_LIB_CONCEPTS
     325             : 
     326             : namespace concepts
     327             : {
     328             : 
     329             : template <typename T>
     330             : concept Complete = requires { sizeof (T); };
     331             : 
     332             : // Note: this mirrors the named requirements, not the standard concepts, so we don't require
     333             : // the destructor to be noexcept for Destructible.
     334             : template <typename T>
     335             : concept Destructible = std::is_destructible<T>::value;
     336             : 
     337             : template <typename T>
     338             : concept TriviallyDestructible = std::is_trivially_destructible<T>::value;
     339             : 
     340             : template <typename T>
     341             : concept NoThrowDestructible = std::is_nothrow_destructible<T>::value;
     342             : 
     343             : // Note: this mirrors the named requirements, not the standard library concepts,
     344             : // so we don't require Destructible here.
     345             : 
     346             : template <typename T, typename... Args>
     347             : concept ConstructibleFrom = std::is_constructible<T, Args...>::value;
     348             : 
     349             : template <typename T, typename... Args>
     350             : concept NoThrowConstructibleFrom = std::is_nothrow_constructible<T, Args...>::value;
     351             : 
     352             : template <typename From, typename To>
     353             : concept ConvertibleTo =
     354             :   std::is_convertible<From, To>::value
     355             :   &&  requires (typename std::add_rvalue_reference<From>::type (&f) (void))
     356             : {
     357             :   static_cast<To> (f ());
     358             : };
     359             : 
     360             : template <typename From, typename To>
     361             : concept NoThrowConvertibleTo =
     362             :   std::is_nothrow_convertible<From, To>::value
     363             :   &&  requires (typename std::add_rvalue_reference<From>::type (&f) (void) noexcept)
     364             : {
     365             :   { static_cast<To> (f ()) } noexcept;
     366             : };
     367             : 
     368             : // Note: std::default_initializable requires std::destructible.
     369             : template <typename T>
     370             : concept DefaultConstructible =
     371             :   ConstructibleFrom<T>
     372             :   &&  requires { T { }; }
     373             :   &&  requires { ::new (static_cast<void *> (nullptr)) T; };
     374             : 
     375             : template <typename T>
     376             : concept MoveAssignable = std::assignable_from<T&, T>;
     377             : 
     378             : template <typename T>
     379             : concept CopyAssignable =
     380             :   MoveAssignable<T>
     381             :   &&  std::assignable_from<T&, T&>
     382             :   &&  std::assignable_from<T&, const T&>
     383             :   &&  std::assignable_from<T&, const T>;
     384             : 
     385             : template <typename T>
     386             : concept MoveConstructible = ConstructibleFrom<T, T> && ConvertibleTo<T, T>;
     387             : 
     388             : template <typename T>
     389             : concept NoThrowMoveConstructible =
     390             :   NoThrowConstructibleFrom<T, T>
     391             :   &&  NoThrowConvertibleTo<T, T>;
     392             : 
     393             : template <typename T>
     394             : concept CopyConstructible =
     395             :   MoveConstructible<T>
     396             :   &&  ConstructibleFrom<T,       T&> && ConvertibleTo<      T&, T>
     397             :   &&  ConstructibleFrom<T, const T&> && ConvertibleTo<const T&, T>
     398             :   &&  ConstructibleFrom<T, const T > && ConvertibleTo<const T, T>;
     399             : 
     400             : template <typename T>
     401             : concept NoThrowCopyConstructible =
     402             :   NoThrowMoveConstructible<T>
     403             :   &&  NoThrowConstructibleFrom<T,       T&> && NoThrowConvertibleTo<      T&, T>
     404             :   &&  NoThrowConstructibleFrom<T, const T&> && NoThrowConvertibleTo<const T&, T>
     405             :   &&  NoThrowConstructibleFrom<T, const T > && NoThrowConvertibleTo<const T, T>;
     406             : 
     407             : template <typename T>
     408             : concept Swappable = std::swappable<T>;
     409             : 
     410             : template <typename T>
     411             : concept EqualityComparable = std::equality_comparable<T>;
     412             : 
     413             : // T is a type
     414             : // X is a Container
     415             : // A is an Allocator
     416             : // if X::allocator_type then
     417             : //   std::same_as<typename X::allocator_type,
     418             : //                typename std::allocator_traits<A>::template rebind_alloc<T>>
     419             : // otherwise
     420             : //   no condition; we use std::allocator<T> regardless of A
     421             : //
     422             : // see [22.2.1].16
     423             : template <typename T, typename X, typename A, typename ...Args>
     424             : concept EmplaceConstructible =
     425             :   std::same_as<typename X::value_type, T>
     426             :   &&  (  (  requires { typename X::allocator_type; } // only perform this check if X is
     427             :             &&  std::same_as<typename X::allocator_type, // allocator-aware
     428             :             typename std::allocator_traits<A>::template rebind_alloc<T>>
     429             :             &&  (  requires (A m, T *p, Args&&... args)
     430             : {
     431             :   m.construct (p, std::forward<Args> (args)...);
     432             : }
     433             : ||  requires (T *p, Args&&... args)
     434             : {
     435             : #if __cplusplus >= 202002L // c++20 fully featured
     436             :   { std::construct_at (p, std::forward<Args> (args)...) } -> std::same_as<T *>;
     437             : #else
     438             :   ::new (std::declval<void *> ()) T (std::declval<Args> ()...);
     439             : #endif
     440             : }))
     441             : ||  (! requires { typename X::allocator_type; }
     442             :      &&  requires (T *p, Args&&... args)
     443             : {
     444             : #if __cplusplus >= 202002L // c++20 fully featured
     445             :   { std::construct_at (p, std::forward<Args> (args)...) } -> std::same_as<T *>;
     446             : #else
     447             :   ::new (std::declval<void *> ()) T (std::declval<Args> ()...);
     448             : #endif
     449             : }));
     450             : 
     451             : template <typename T, typename X,
     452             : typename A = typename std::conditional<requires { typename X::allocator_type; },
     453             :          typename X::allocator_type,
     454             :          std::allocator<T>>::type>
     455             :          concept DefaultInsertable = EmplaceConstructible<T, X, A>;
     456             : 
     457             : template <typename T, typename X,
     458             : typename A = typename std::conditional<requires { typename X::allocator_type; },
     459             :          typename X::allocator_type,
     460             :          std::allocator<T>>::type>
     461             :          concept MoveInsertable = EmplaceConstructible<T, X, A, T>;
     462             : 
     463             : template <typename T, typename X,
     464             : typename A = typename std::conditional<requires { typename X::allocator_type; },
     465             :          typename X::allocator_type,
     466             :          std::allocator<T>>::type>
     467             :          concept CopyInsertable = MoveInsertable<T, X, A>
     468             :                                   &&  EmplaceConstructible<T, X, A,       T&>
     469             :                                   &&  EmplaceConstructible<T, X, A, const T&>;
     470             : 
     471             : // same method as with EmplaceConstructible
     472             : template <typename T, typename X,
     473             : typename A = typename std::conditional<requires { typename X::allocator_type; },
     474             :          typename X::allocator_type,
     475             :          std::allocator<T>>::type>
     476             :          concept Erasable =
     477             :            std::same_as<typename X::value_type, T>
     478             :            &&  (  (  requires { typename X::allocator_type; } // if X is allocator aware
     479             :                      &&  std::same_as<typename X::allocator_type,
     480             :                      typename std::allocator_traits<A>::template rebind_alloc<T>>
     481             :                   &&  (  requires (A m, T *p)
     482             : {
     483             :   m.destroy (p);
     484             : }
     485             : ||   std::is_destructible<T>::value))
     486             : ||  (! requires { typename X::allocator_type; }
     487             :      &&  std::is_destructible<T>::value));
     488             : 
     489             : template <typename T>
     490             : concept ContextuallyConvertibleToBool = std::constructible_from<bool, T>;
     491             : 
     492             : template <typename T>
     493             : concept BoolConstant = std::derived_from<T, std::true_type>
     494             : || std::derived_from<T, std::false_type>;
     495             : 
     496             : template <typename T>
     497             : concept NullablePointer =
     498             : EqualityComparable<T>
     499             : &&  DefaultConstructible<T>
     500             : &&  CopyConstructible<T>
     501             : &&  CopyAssignable<T>
     502             : &&  Destructible<T>
     503             : &&  ConstructibleFrom<T, std::nullptr_t>
     504             : &&  ConvertibleTo<std::nullptr_t, T>
     505             : &&  requires (T p, T q, std::nullptr_t np)
     506             : {
     507             :   T (np);
     508             :   { p = np   } -> std::same_as<T&>;
     509             :   { p  != q  } -> ContextuallyConvertibleToBool;
     510             :   { p  == np } -> ContextuallyConvertibleToBool;
     511             :   { np == p  } -> ContextuallyConvertibleToBool;
     512             :   { p  != np } -> ContextuallyConvertibleToBool;
     513             :   { np != p  } -> ContextuallyConvertibleToBool;
     514             : };
     515             : 
     516             : static_assert (  NullablePointer<int *>);
     517             : static_assert (! NullablePointer<int>);
     518             : 
     519             : template <typename A, typename T, typename U = T *>
     520             : concept AllocatorFor =
     521             : NoThrowCopyConstructible<A>
     522             : &&  requires (A a,
     523             :               typename std::allocator_traits<A>::template rebind_alloc<U> b,
     524             :               U xp,
     525             :               typename std::allocator_traits<A>::pointer p,
     526             :               typename std::allocator_traits<A>::const_pointer cp,
     527             :               typename std::allocator_traits<A>::void_pointer vp,
     528             :               typename std::allocator_traits<A>::const_void_pointer cvp,
     529             :               typename std::allocator_traits<A>::value_type& r,
     530             :               typename std::allocator_traits<A>::size_type n)
     531             : {
     532             :   /** Inner types **/
     533             :   // A::pointer
     534             :   requires NullablePointer<            typename std::allocator_traits<A>::pointer>;
     535             :   requires std::random_access_iterator<typename std::allocator_traits<A>::pointer>;
     536             :   requires std::contiguous_iterator<   typename std::allocator_traits<A>::pointer>;
     537             : 
     538             :   // A::const_pointer
     539             :   requires NullablePointer<            typename std::allocator_traits<A>::const_pointer>;
     540             :   requires std::random_access_iterator<typename std::allocator_traits<A>::const_pointer>;
     541             :   requires std::contiguous_iterator<   typename std::allocator_traits<A>::const_pointer>;
     542             : 
     543             :   requires std::convertible_to<typename std::allocator_traits<A>::pointer,
     544             :            typename std::allocator_traits<A>::const_pointer>;
     545             : 
     546             :   // A::void_pointer
     547             :   requires NullablePointer<typename std::allocator_traits<A>::void_pointer>;
     548             : 
     549             :   requires std::convertible_to<typename std::allocator_traits<A>::pointer,
     550             :            typename std::allocator_traits<A>::void_pointer>;
     551             : 
     552             :   requires std::same_as<typename std::allocator_traits<A>::void_pointer,
     553             :            typename std::allocator_traits<decltype (b)>::void_pointer>;
     554             : 
     555             :   // A::const_void_pointer
     556             :   requires NullablePointer<typename std::allocator_traits<A>::const_void_pointer>;
     557             : 
     558             :   requires std::convertible_to<typename std::allocator_traits<A>::pointer,
     559             :            typename std::allocator_traits<A>::const_void_pointer>;
     560             : 
     561             :   requires std::convertible_to<typename std::allocator_traits<A>::const_pointer,
     562             :            typename std::allocator_traits<A>::const_void_pointer>;
     563             : 
     564             :   requires std::convertible_to<typename std::allocator_traits<A>::void_pointer,
     565             :            typename std::allocator_traits<A>::const_void_pointer>;
     566             : 
     567             :   requires std::same_as<typename std::allocator_traits<A>::const_void_pointer,
     568             :            typename std::allocator_traits<decltype (b)>::const_void_pointer>;
     569             : 
     570             :   // A::value_type
     571             :   typename A::value_type;
     572             :   requires std::same_as<typename A::value_type, T>;
     573             :   requires std::same_as<typename A::value_type,
     574             :            typename std::allocator_traits<A>::value_type>;
     575             : 
     576             :   // A::size_type
     577             :   requires std::unsigned_integral<typename std::allocator_traits<A>::size_type>;
     578             : 
     579             :   // A::difference_type
     580             :   requires std::signed_integral<typename std::allocator_traits<A>::difference_type>;
     581             : 
     582             :   // A::template rebind<U>::other [optional]
     583             :   requires ! requires { typename A::template rebind<U>::other; }
     584             :   ||  requires
     585             :   {
     586             :     requires std::same_as<decltype (b), typename A::template rebind<U>::other>;
     587             :     requires std::same_as<A, typename decltype (b)::template rebind<T>::other>;
     588             :   };
     589             : 
     590             :   /** Operations on pointers **/
     591             :   { *p  } -> std::same_as<typename A::value_type&>;
     592             :   { *cp } -> std::same_as<const typename A::value_type&>;
     593             : 
     594             :   // Language in the standard implies that `decltype (p)` must either
     595             :   // be a raw pointer or implement `operator->`. There is no mention
     596             :   // of `std::to_address` or `std::pointer_traits<Ptr>::to_address`.
     597             :   requires std::same_as<decltype (p), typename A::value_type *>
     598             :   ||  requires
     599             :   {
     600             :     { p.operator-> () } -> std::same_as<typename A::value_type *>;
     601             :   };
     602             : 
     603             :   requires std::same_as<decltype (cp), const typename A::value_type *>
     604             :   ||  requires
     605             :   {
     606             :     { cp.operator-> () } -> std::same_as<const typename A::value_type *>;
     607             :   };
     608             : 
     609             :   { static_cast<decltype (p)> (vp)   } -> std::same_as<decltype (p)>;
     610             :   { static_cast<decltype (cp)> (cvp) } -> std::same_as<decltype (cp)>;
     611             : 
     612             :   { std::pointer_traits<decltype (p)>::pointer_to (r) } -> std::same_as<decltype (p)>;
     613             : 
     614             :   /** Storage and lifetime operations **/
     615             :   // a.allocate (n)
     616             :   { a.allocate (n) } -> std::same_as<decltype (p)>;
     617             : 
     618             :   // a.allocate (n, cvp) [optional]
     619             :   requires ! requires { a.allocate (n, cvp); }
     620             :   ||  requires { { a.allocate (n, cvp) } -> std::same_as<decltype (p)>; };
     621             : 
     622             :   // a.deallocate (p, n)
     623             :   { a.deallocate (p, n) } -> std::convertible_to<void>;
     624             : 
     625             :   // a.max_size () [optional]
     626             :   requires ! requires { a.max_size (); }
     627             :   ||  requires { { a.max_size () } -> std::same_as<decltype (n)>; };
     628             : 
     629             :   // a.construct (xp, args) [optional]
     630             :   requires ! requires { a.construct (xp); }
     631             :   ||  requires { { a.construct (xp) } -> std::convertible_to<void>; };
     632             : 
     633             :   // a.destroy (xp) [optional]
     634             :   requires ! requires { a.destroy (xp); }
     635             :   ||  requires { { a.destroy (xp) } -> std::convertible_to<void>; };
     636             : 
     637             :   /** Relationship between instances **/
     638             :   requires NoThrowConstructibleFrom<A, decltype (b)>;
     639             :   requires NoThrowConstructibleFrom<A, decltype (std::move (b))>;
     640             : 
     641             :   requires BoolConstant<typename std::allocator_traits<A>::is_always_equal>;
     642             : 
     643             :   /** Influence on container operations **/
     644             :   // a.select_on_container_copy_construction () [optional]
     645             :   requires ! requires { a.select_on_container_copy_construction (); }
     646             :   ||  requires
     647             :   {
     648             :     { a.select_on_container_copy_construction () } -> std::same_as<A>;
     649             :   };
     650             : 
     651             :   requires BoolConstant<
     652             :   typename std::allocator_traits<A>::propagate_on_container_copy_assignment>;
     653             : 
     654             :   requires BoolConstant<
     655             :   typename std::allocator_traits<A>::propagate_on_container_move_assignment>;
     656             : 
     657             :   requires BoolConstant<
     658             :   typename std::allocator_traits<A>::propagate_on_container_swap>;
     659             : 
     660             :   { a == b } -> std::same_as<bool>;
     661             :   { a != b } -> std::same_as<bool>;
     662             : }
     663             : &&  requires (A a1, A a2)
     664             : {
     665             :   { a1 == a2 } -> std::same_as<bool>;
     666             :   { a1 != a2 } -> std::same_as<bool>;
     667             : };
     668             : 
     669             : static_assert (AllocatorFor<std::allocator<int>, int>,
     670             :                "std::allocator<int> failed to meet Allocator concept requirements.");
     671             : 
     672             : template <typename A>
     673             : concept Allocator = AllocatorFor<A, typename A::value_type>;
     674             : 
     675             : namespace small_vector
     676             : {
     677             : 
     678             : // Basically, these shut off the concepts if we have an incomplete type.
     679             : // This namespace is only needed because of issues on Clang
     680             : // preventing us from short-circuiting for incomplete types.
     681             : 
     682             : template <typename T>
     683             : concept Destructible =
     684             : ! concepts::Complete<T> || concepts::Destructible<T>;
     685             : 
     686             : template <typename T>
     687             : concept MoveAssignable =
     688             : ! concepts::Complete<T> || concepts::MoveAssignable<T>;
     689             : 
     690             : template <typename T>
     691             : concept CopyAssignable =
     692             : ! concepts::Complete<T> || concepts::CopyAssignable<T>;
     693             : 
     694             : template <typename T>
     695             : concept MoveConstructible =
     696             : ! concepts::Complete<T> || concepts::MoveConstructible<T>;
     697             : 
     698             : template <typename T>
     699             : concept CopyConstructible =
     700             : ! concepts::Complete<T> || concepts::CopyConstructible<T>;
     701             : 
     702             : template <typename T>
     703             : concept Swappable =
     704             : ! concepts::Complete<T> || concepts::Swappable<T>;
     705             : 
     706             : template <typename T, typename SmallVector, typename Alloc>
     707             : concept DefaultInsertable =
     708             : ! concepts::Complete<T> || concepts::DefaultInsertable<T, SmallVector, Alloc>;
     709             : 
     710             : template <typename T, typename SmallVector, typename Alloc>
     711             : concept MoveInsertable =
     712             : ! concepts::Complete<T> || concepts::MoveInsertable<T, SmallVector, Alloc>;
     713             : 
     714             : template <typename T, typename SmallVector, typename Alloc>
     715             : concept CopyInsertable =
     716             : ! concepts::Complete<T> || concepts::CopyInsertable<T, SmallVector, Alloc>;
     717             : 
     718             : template <typename T, typename SmallVector, typename Alloc>
     719             : concept Erasable =
     720             : ! concepts::Complete<T> || concepts::Erasable<T, SmallVector, Alloc>;
     721             : 
     722             : template <typename T, typename SmallVector, typename Alloc, typename ...Args>
     723             : concept EmplaceConstructible =
     724             : ! concepts::Complete<T> || concepts::EmplaceConstructible<T, SmallVector, Alloc, Args...>;
     725             : 
     726             : template <typename Alloc, typename T>
     727             : concept AllocatorFor =
     728             : ! concepts::Complete<T> || concepts::AllocatorFor<Alloc, T>;
     729             : 
     730             : template <typename Alloc>
     731             : concept Allocator = AllocatorFor<Alloc, typename Alloc::value_type>;
     732             : 
     733             : } // namespace gch::concepts::small_vector
     734             : 
     735             : } // namespace gch::concepts
     736             : 
     737             : #endif
     738             : 
     739             : template <typename Allocator>
     740             : #ifdef PLUMED_GCH_LIB_CONCEPTS
     741             : requires concepts::small_vector::Allocator<Allocator>
     742             : #endif
     743             : struct default_buffer_size;
     744             : 
     745             : template <typename T,
     746             :           unsigned InlineCapacity = default_buffer_size<std::allocator<T>>::value,
     747             :           typename Allocator      = std::allocator<T>>
     748             : #ifdef PLUMED_GCH_LIB_CONCEPTS
     749             : requires concepts::small_vector::AllocatorFor<Allocator, T>
     750             : #endif
     751             : class small_vector;
     752             : 
     753             : template <typename Allocator>
     754             : #ifdef PLUMED_GCH_LIB_CONCEPTS
     755             : requires concepts::small_vector::Allocator<Allocator>
     756             : #endif
     757             : struct default_buffer_size
     758             : {
     759             : private:
     760             :   template <typename, typename Enable = void>
     761             :   struct is_complete
     762             : : std::false_type
     763             :   { };
     764             : 
     765             :   template <typename U>
     766             :   struct is_complete<U, decltype (static_cast<void> (sizeof (U)))>
     767             : : std::true_type
     768             :   { };
     769             : 
     770             : public:
     771             :   using allocator_type     = Allocator;
     772             :   using value_type         = typename std::allocator_traits<allocator_type>::value_type;
     773             :   using empty_small_vector = small_vector<value_type, 0, allocator_type>;
     774             : 
     775             :   static_assert (is_complete<value_type>::value,
     776             :                  "Calculation of a default number of elements requires that `T` be complete.");
     777             : 
     778             :   static constexpr
     779             :   unsigned
     780             :   buffer_max = 256;
     781             : 
     782             :   static constexpr
     783             :   unsigned
     784             :   ideal_total = PLUMED_GCH_SMALL_VECTOR_DEFAULT_SIZE;
     785             : 
     786             : #ifndef PLUMED_GCH_UNRESTRICTED_DEFAULT_BUFFER_SIZE
     787             : 
     788             :   // FIXME: Some compilers will not emit the error from this static_assert
     789             :   //        while instantiating a small_vector, and attribute the mistake
     790             :   //        to some random other function.
     791             :   // static_assert (sizeof (value_type) <= buffer_max, "`sizeof (T)` too large");
     792             : 
     793             : #endif
     794             : 
     795             :   static constexpr
     796             :   unsigned
     797             :   ideal_buffer = ideal_total - sizeof (empty_small_vector);
     798             : 
     799             :   static_assert (sizeof (empty_small_vector) != 0,
     800             :                  "Empty `small_vector` should not have size 0.");
     801             : 
     802             :   static_assert (ideal_buffer < ideal_total,
     803             :                  "Empty `small_vector` is larger than ideal_total.");
     804             : 
     805             :   static constexpr
     806             :   unsigned
     807             :   value = (sizeof (value_type) <= ideal_buffer) ? (ideal_buffer / sizeof (value_type)) : 1;
     808             : };
     809             : 
     810             : #ifdef PLUMED_GCH_VARIABLE_TEMPLATES
     811             : 
     812             : template <typename Allocator>
     813             : PLUMED_GCH_INLINE_VARIABLE constexpr
     814             : unsigned
     815             : default_buffer_size_v = default_buffer_size<Allocator>::value;
     816             : 
     817             : #endif
     818             : 
     819             : template <typename Pointer, typename DifferenceType>
     820             : class small_vector_iterator
     821             : {
     822             : public:
     823             :   using difference_type   = DifferenceType;
     824             :   using value_type        = typename std::iterator_traits<Pointer>::value_type;
     825             :   using pointer           = typename std::iterator_traits<Pointer>::pointer;
     826             :   using reference         = typename std::iterator_traits<Pointer>::reference;
     827             :   using iterator_category = typename std::iterator_traits<Pointer>::iterator_category;
     828             : #ifdef PLUMED_GCH_LIB_CONCEPTS
     829             :   using iterator_concept  = std::contiguous_iterator_tag;
     830             : #endif
     831             : 
     832             : //  small_vector_iterator            (void)                             = impl;
     833             :   small_vector_iterator            (const small_vector_iterator&)     = default;
     834             :   small_vector_iterator            (small_vector_iterator&&) noexcept = default;
     835             :   small_vector_iterator& operator= (const small_vector_iterator&)     = default;
     836             :   small_vector_iterator& operator= (small_vector_iterator&&) noexcept = default;
     837             :   ~small_vector_iterator           (void)                             = default;
     838             : 
     839             : #ifdef NDEBUG
     840             :   small_vector_iterator (void) = default;
     841             : #else
     842             :   constexpr
     843             :   small_vector_iterator (void) noexcept
     844             :     : m_ptr ()
     845             :   { }
     846             : #endif
     847             : 
     848             :   constexpr explicit
     849             :   small_vector_iterator (const Pointer& p) noexcept
     850             :     : m_ptr (p)
     851             :   { }
     852             : 
     853             :   template <typename U, typename D,
     854             :             typename std::enable_if<std::is_convertible<U, Pointer>::value>::type * = nullptr>
     855             :   constexpr PLUMED_GCH_IMPLICIT_CONVERSION
     856             :   small_vector_iterator (const small_vector_iterator<U, D>& other) noexcept
     857             :     : m_ptr (other.base ())
     858             :   { }
     859             : 
     860             :   PLUMED_GCH_CPP14_CONSTEXPR
     861             :   small_vector_iterator&
     862             :   operator++ (void) noexcept
     863             :   {
     864             :     ++m_ptr;
     865             :     return *this;
     866             :   }
     867             : 
     868             :   PLUMED_GCH_CPP14_CONSTEXPR
     869             :   small_vector_iterator
     870             :   operator++ (int) noexcept
     871             :   {
     872             :     return small_vector_iterator (m_ptr++);
     873             :   }
     874             : 
     875             :   PLUMED_GCH_CPP14_CONSTEXPR
     876             :   small_vector_iterator&
     877             :   operator-- (void) noexcept
     878             :   {
     879     1797525 :     --m_ptr;
     880             :     return *this;
     881             :   }
     882             : 
     883             :   PLUMED_GCH_CPP14_CONSTEXPR
     884             :   small_vector_iterator
     885             :   operator-- (int) noexcept
     886             :   {
     887             :     return small_vector_iterator (m_ptr--);
     888             :   }
     889             : 
     890             :   PLUMED_GCH_CPP14_CONSTEXPR
     891             :   small_vector_iterator&
     892             :   operator+= (difference_type n) noexcept
     893             :   {
     894             :     m_ptr += n;
     895             :     return *this;
     896             :   }
     897             : 
     898             :   constexpr
     899             :   small_vector_iterator
     900             :   operator+ (difference_type n) const noexcept
     901             :   {
     902    12826778 :     return small_vector_iterator (m_ptr + n);
     903             :   }
     904             : 
     905             :   PLUMED_GCH_CPP14_CONSTEXPR
     906             :   small_vector_iterator&
     907             :   operator-= (difference_type n) noexcept
     908             :   {
     909             :     m_ptr -= n;
     910             :     return *this;
     911             :   }
     912             : 
     913             :   constexpr
     914             :   small_vector_iterator
     915             :   operator- (difference_type n) const noexcept
     916             :   {
     917     2386656 :     return small_vector_iterator (m_ptr - n);
     918             :   }
     919             : 
     920             :   constexpr
     921             :   reference
     922             :   operator* (void) const noexcept
     923             :   {
     924             : #ifdef PLUMED_GCH_LIB_LAUNDER
     925             :     return launder_and_dereference (m_ptr);
     926             : #else
     927             :     return *m_ptr;
     928             : #endif
     929             :   }
     930             : 
     931             :   constexpr
     932             :   pointer
     933             :   operator-> (void) const noexcept
     934             :   {
     935             :     return get_pointer (m_ptr);
     936             :   }
     937             : 
     938             :   constexpr
     939             :   reference
     940             :   operator[] (difference_type n) const noexcept
     941             :   {
     942             : #ifdef PLUMED_GCH_LIB_LAUNDER
     943   142075517 :     return launder_and_dereference (m_ptr + n);
     944             : #else
     945             :     return m_ptr[n];
     946             : #endif
     947             :   }
     948             : 
     949             :   constexpr
     950             :   const Pointer&
     951             :   base (void) const noexcept
     952             :   {
     953             :     return m_ptr;
     954             :   }
     955             : 
     956             : private:
     957             :   template <typename Ptr = Pointer,
     958             :             typename std::enable_if<std::is_pointer<Ptr>::value, bool>::type = true>
     959             :   static constexpr
     960             :   pointer
     961             :   get_pointer (Pointer ptr) noexcept
     962             :   {
     963             :     return ptr;
     964             :   }
     965             : 
     966             :   template <typename Ptr = Pointer,
     967             :             typename std::enable_if<! std::is_pointer<Ptr>::value, bool>::type = false>
     968             :   static constexpr
     969             :   pointer
     970             :   get_pointer (Pointer ptr) noexcept
     971             :   {
     972             :     // Given the requirements for Allocator, Pointer must either be a raw pointer, or
     973             :     // have a defined operator-> which returns a raw pointer.
     974             :     return ptr.operator-> ();
     975             :   }
     976             : 
     977             : #ifdef PLUMED_GCH_LIB_LAUNDER
     978             : 
     979             :   template <typename Ptr = Pointer,
     980             :             typename std::enable_if<std::is_pointer<Ptr>::value, bool>::type = true>
     981             :   static constexpr
     982             :   reference
     983             :   launder_and_dereference (Pointer ptr) noexcept
     984             :   {
     985             :     return *std::launder (ptr);
     986             :   }
     987             : 
     988             :   template <typename Ptr = Pointer,
     989             :             typename std::enable_if<! std::is_pointer<Ptr>::value, bool>::type = false>
     990             :   static constexpr
     991             :   reference
     992             :   launder_and_dereference (Pointer ptr) noexcept
     993             :   {
     994             :     return *ptr;
     995             :   }
     996             : 
     997             : #endif
     998             : 
     999             :   Pointer m_ptr;
    1000             : };
    1001             : 
    1002             : #ifdef PLUMED_GCH_LIB_THREE_WAY_COMPARISON
    1003             : 
    1004             : template <typename PointerLHS, typename DifferenceTypeLHS,
    1005             :           typename PointerRHS, typename DifferenceTypeRHS>
    1006             : constexpr
    1007             : bool
    1008             : operator== (const small_vector_iterator<PointerLHS, DifferenceTypeLHS>& lhs,
    1009             :             const small_vector_iterator<PointerRHS, DifferenceTypeRHS>& rhs)
    1010             : noexcept (noexcept (lhs.base () == rhs.base ()))
    1011             : requires requires { { lhs.base () == rhs.base () } -> std::convertible_to<bool>; }
    1012             : {
    1013             :   return lhs.base () == rhs.base ();
    1014             : }
    1015             : 
    1016             : template <typename Pointer, typename DifferenceType>
    1017             : constexpr
    1018             : bool
    1019             : operator== (const small_vector_iterator<Pointer, DifferenceType>& lhs,
    1020             :             const small_vector_iterator<Pointer, DifferenceType>& rhs)
    1021             : noexcept (noexcept (lhs.base () == rhs.base ()))
    1022             : requires requires { { lhs.base () == rhs.base () } -> std::convertible_to<bool>; }
    1023             : {
    1024             :   return lhs.base () == rhs.base ();
    1025             : }
    1026             : 
    1027             : template <typename PointerLHS, typename DifferenceTypeLHS,
    1028             :           typename PointerRHS, typename DifferenceTypeRHS>
    1029             : requires std::three_way_comparable_with<PointerLHS, PointerRHS>
    1030             : constexpr
    1031             : auto
    1032             : operator<=> (const small_vector_iterator<PointerLHS, DifferenceTypeLHS>& lhs,
    1033             :              const small_vector_iterator<PointerRHS, DifferenceTypeRHS>& rhs)
    1034             : noexcept (noexcept (lhs.base () <=> rhs.base ()))
    1035             : {
    1036             :   return lhs.base () <=> rhs.base ();
    1037             : }
    1038             : 
    1039             : template <typename Pointer, typename DifferenceType>
    1040             : requires std::three_way_comparable<Pointer>
    1041             : constexpr
    1042             : auto
    1043             : operator<=> (const small_vector_iterator<Pointer, DifferenceType>& lhs,
    1044             :              const small_vector_iterator<Pointer, DifferenceType>& rhs)
    1045             : noexcept (noexcept (lhs.base () <=> rhs.base ()))
    1046             : {
    1047             :   return lhs.base () <=> rhs.base ();
    1048             : }
    1049             : 
    1050             : template <typename PointerLHS, typename DifferenceTypeLHS,
    1051             :           typename PointerRHS, typename DifferenceTypeRHS>
    1052             : constexpr
    1053             : auto
    1054             : operator<=> (const small_vector_iterator<PointerLHS, DifferenceTypeLHS>& lhs,
    1055             :              const small_vector_iterator<PointerRHS, DifferenceTypeRHS>& rhs)
    1056             : noexcept (noexcept (lhs.base () < rhs.base ()) && noexcept (rhs.base () < lhs.base ()))
    1057             : {
    1058             :   using ordering = std::weak_ordering;
    1059             :   return (lhs.base () < rhs.base ()) ? ordering::less
    1060             :          : (rhs.base () < lhs.base ()) ? ordering::greater
    1061             :          : ordering::equivalent;
    1062             : }
    1063             : 
    1064             : template <typename Pointer, typename DifferenceType>
    1065             : constexpr
    1066             : auto
    1067             : operator<=> (const small_vector_iterator<Pointer, DifferenceType>& lhs,
    1068             :              const small_vector_iterator<Pointer, DifferenceType>& rhs)
    1069             : noexcept (noexcept (lhs.base () < rhs.base ()) && noexcept (rhs.base () < lhs.base ()))
    1070             : {
    1071             :   using ordering = std::weak_ordering;
    1072             :   return (lhs.base () < rhs.base ()) ? ordering::less
    1073             :          : (rhs.base () < lhs.base ()) ? ordering::greater
    1074             :          : ordering::equivalent;
    1075             : }
    1076             : 
    1077             : #else
    1078             : 
    1079             : // Note: Passing this on from "Gaby" in stl_iterator.h -- templated
    1080             : //       comparisons in generic code should have overloads for both
    1081             : //       homogenous and heterogeneous types. This is because we get
    1082             : //       ambiguous overload resolution when std::rel_ops is visible
    1083             : //       (ie. `using namespace std::rel_ops`).
    1084             : 
    1085             : template <typename PointerLHS, typename DifferenceTypeLHS,
    1086             :           typename PointerRHS, typename DifferenceTypeRHS>
    1087             : constexpr
    1088             : bool
    1089             : operator== (const small_vector_iterator<PointerLHS, DifferenceTypeLHS>& lhs,
    1090             :             const small_vector_iterator<PointerRHS, DifferenceTypeRHS>& rhs) noexcept
    1091             : {
    1092             :   return lhs.base () == rhs.base ();
    1093             : }
    1094             : 
    1095             : template <typename Pointer, typename DifferenceType>
    1096             : constexpr
    1097             : bool
    1098             : operator== (const small_vector_iterator<Pointer, DifferenceType>& lhs,
    1099             :             const small_vector_iterator<Pointer, DifferenceType>& rhs) noexcept
    1100             : {
    1101             :   return lhs.base () == rhs.base ();
    1102             : }
    1103             : 
    1104             : template <typename PointerLHS, typename DifferenceTypeLHS,
    1105             :           typename PointerRHS, typename DifferenceTypeRHS>
    1106             : constexpr
    1107             : bool
    1108             : operator!= (const small_vector_iterator<PointerLHS, DifferenceTypeLHS>& lhs,
    1109             :             const small_vector_iterator<PointerRHS, DifferenceTypeRHS>& rhs) noexcept
    1110             : {
    1111             :   return lhs.base () != rhs.base ();
    1112             : }
    1113             : 
    1114             : template <typename Pointer, typename DifferenceType>
    1115             : constexpr
    1116             : bool
    1117             : operator!= (const small_vector_iterator<Pointer, DifferenceType>& lhs,
    1118             :             const small_vector_iterator<Pointer, DifferenceType>& rhs) noexcept
    1119             : {
    1120             :   return lhs.base () != rhs.base ();
    1121             : }
    1122             : 
    1123             : template <typename PointerLHS, typename DifferenceTypeLHS,
    1124             :           typename PointerRHS, typename DifferenceTypeRHS>
    1125             : constexpr
    1126             : bool
    1127             : operator< (const small_vector_iterator<PointerLHS, DifferenceTypeLHS>& lhs,
    1128             :            const small_vector_iterator<PointerRHS, DifferenceTypeRHS>& rhs) noexcept
    1129             : {
    1130             :   return lhs.base () < rhs.base ();
    1131             : }
    1132             : 
    1133             : template <typename Pointer, typename DifferenceType>
    1134             : constexpr
    1135             : bool
    1136             : operator< (const small_vector_iterator<Pointer, DifferenceType>& lhs,
    1137             :            const small_vector_iterator<Pointer, DifferenceType>& rhs) noexcept
    1138             : {
    1139             :   return lhs.base () < rhs.base ();
    1140             : }
    1141             : 
    1142             : template <typename PointerLHS, typename DifferenceTypeLHS,
    1143             :           typename PointerRHS, typename DifferenceTypeRHS>
    1144             : constexpr
    1145             : bool
    1146             : operator>= (const small_vector_iterator<PointerLHS, DifferenceTypeLHS>& lhs,
    1147             :             const small_vector_iterator<PointerRHS, DifferenceTypeRHS>& rhs) noexcept
    1148             : {
    1149             :   return lhs.base () >= rhs.base ();
    1150             : }
    1151             : 
    1152             : template <typename Pointer, typename DifferenceType>
    1153             : constexpr
    1154             : bool
    1155             : operator>= (const small_vector_iterator<Pointer, DifferenceType>& lhs,
    1156             :             const small_vector_iterator<Pointer, DifferenceType>& rhs) noexcept
    1157             : {
    1158             :   return lhs.base () >= rhs.base ();
    1159             : }
    1160             : 
    1161             : template <typename PointerLHS, typename DifferenceTypeLHS,
    1162             :           typename PointerRHS, typename DifferenceTypeRHS>
    1163             : constexpr
    1164             : bool
    1165             : operator> (const small_vector_iterator<PointerLHS, DifferenceTypeLHS>& lhs,
    1166             :            const small_vector_iterator<PointerRHS, DifferenceTypeRHS>& rhs) noexcept
    1167             : {
    1168             :   return lhs.base () > rhs.base ();
    1169             : }
    1170             : 
    1171             : template <typename Pointer, typename DifferenceType>
    1172             : constexpr
    1173             : bool
    1174             : operator> (const small_vector_iterator<Pointer, DifferenceType>& lhs,
    1175             :            const small_vector_iterator<Pointer, DifferenceType>& rhs) noexcept
    1176             : {
    1177             :   return lhs.base () > rhs.base ();
    1178             : }
    1179             : 
    1180             : template <typename PointerLHS, typename DifferenceTypeLHS,
    1181             :           typename PointerRHS, typename DifferenceTypeRHS>
    1182             : constexpr
    1183             : bool
    1184             : operator<= (const small_vector_iterator<PointerLHS, DifferenceTypeLHS>& lhs,
    1185             :             const small_vector_iterator<PointerRHS, DifferenceTypeRHS>& rhs) noexcept
    1186             : {
    1187             :   return lhs.base () <= rhs.base ();
    1188             : }
    1189             : 
    1190             : template <typename Pointer, typename DifferenceType>
    1191             : constexpr
    1192             : bool
    1193             : operator<= (const small_vector_iterator<Pointer, DifferenceType>& lhs,
    1194             :             const small_vector_iterator<Pointer, DifferenceType>& rhs) noexcept
    1195             : {
    1196             :   return lhs.base () <= rhs.base ();
    1197             : }
    1198             : 
    1199             : #endif
    1200             : 
    1201             : template <typename PointerLHS, typename PointerRHS, typename DifferenceType>
    1202             : constexpr
    1203             : DifferenceType
    1204             : operator- (const small_vector_iterator<PointerLHS, DifferenceType>& lhs,
    1205             :            const small_vector_iterator<PointerRHS, DifferenceType>& rhs) noexcept
    1206             : {
    1207             :   return static_cast<DifferenceType> (lhs.base () - rhs.base ());
    1208             : }
    1209             : 
    1210             : template <typename Pointer, typename DifferenceType>
    1211             : constexpr
    1212             : DifferenceType
    1213             : operator- (const small_vector_iterator<Pointer, DifferenceType>& lhs,
    1214             :            const small_vector_iterator<Pointer, DifferenceType>& rhs) noexcept
    1215             : {
    1216     6755185 :   return static_cast<DifferenceType> (lhs.base () - rhs.base ());
    1217             : }
    1218             : 
    1219             : template <typename Pointer, typename DifferenceType>
    1220             : constexpr
    1221             : small_vector_iterator<Pointer, DifferenceType>
    1222             : operator+ (DifferenceType n, const small_vector_iterator<Pointer, DifferenceType>& it) noexcept
    1223             : {
    1224             :   return it + n;
    1225             : }
    1226             : 
    1227             : namespace detail
    1228             : {
    1229             : 
    1230             : #ifndef PLUMED_GCH_LIB_IS_SWAPPABLE
    1231             : 
    1232             : namespace small_vector_adl
    1233             : {
    1234             : 
    1235             : using std::swap;
    1236             : 
    1237             : template <typename T, typename Enable = void>
    1238             : struct is_nothrow_swappable
    1239             : : std::false_type
    1240             : { };
    1241             : 
    1242             : template <typename T>
    1243             : struct is_nothrow_swappable<T, decltype (swap (std::declval<T&> (), std::declval<T&> ()))>
    1244             : : std::integral_constant<bool, noexcept (swap (std::declval<T&> (), std::declval<T&> ()))>
    1245             : { };
    1246             : 
    1247             : }
    1248             : 
    1249             : #endif
    1250             : 
    1251             : template <typename T, unsigned InlineCapacity>
    1252             : class inline_storage
    1253             : {
    1254             : public:
    1255             :   using value_ty = T;
    1256             : 
    1257             :   inline_storage            (void)                      = default;
    1258             :   inline_storage            (const inline_storage&)     = delete;
    1259             :   inline_storage            (inline_storage&&) noexcept = delete;
    1260             :   inline_storage& operator= (const inline_storage&)     = delete;
    1261             :   inline_storage& operator= (inline_storage&&) noexcept = delete;
    1262             :   ~inline_storage           (void)                      = default;
    1263             : 
    1264             :   PLUMED_GCH_NODISCARD PLUMED_GCH_CPP14_CONSTEXPR
    1265             :   value_ty *
    1266             :   get_inline_ptr (void) noexcept
    1267             :   {
    1268      215674 :     return static_cast<value_ty *> (static_cast<void *> (std::addressof (*m_data)));
    1269             :   }
    1270             : 
    1271             :   PLUMED_GCH_NODISCARD constexpr
    1272             :   const value_ty *
    1273             :   get_inline_ptr (void) const noexcept
    1274             :   {
    1275             :     return static_cast<const value_ty *> (static_cast<const void *> (std::addressof (*m_data)));
    1276             :   }
    1277             : 
    1278             :   static constexpr
    1279             :   std::size_t
    1280             :   element_size (void) noexcept
    1281             :   {
    1282             :     return sizeof (value_ty);
    1283             :   }
    1284             : 
    1285             :   static constexpr
    1286             :   std::size_t
    1287             :   alignment (void) noexcept
    1288             :   {
    1289             :     return alignof (value_ty);
    1290             :   }
    1291             : 
    1292             :   static constexpr
    1293             :   unsigned
    1294             :   num_elements (void) noexcept
    1295             :   {
    1296             :     return InlineCapacity;
    1297             :   }
    1298             : 
    1299             :   static constexpr
    1300             :   std::size_t
    1301             :   num_bytes (void) noexcept
    1302             :   {
    1303             :     return num_elements () * element_size ();
    1304             :   }
    1305             : 
    1306             : private:
    1307             :   typename std::aligned_storage<element_size (), alignment ()>::type m_data[num_elements ()];
    1308             : };
    1309             : 
    1310             : template <typename T>
    1311             : class PLUMED_GCH_EMPTY_BASE inline_storage<T, 0>
    1312             : {
    1313             : public:
    1314             :   using value_ty = T;
    1315             : 
    1316             :   inline_storage            (void)                      = default;
    1317             :   inline_storage            (const inline_storage&)     = delete;
    1318             :   inline_storage            (inline_storage&&) noexcept = delete;
    1319             :   inline_storage& operator= (const inline_storage&)     = delete;
    1320             :   inline_storage& operator= (inline_storage&&) noexcept = delete;
    1321             :   ~inline_storage           (void)                      = default;
    1322             : 
    1323             :   PLUMED_GCH_NODISCARD PLUMED_GCH_CPP14_CONSTEXPR
    1324             :   value_ty *
    1325             :   get_inline_ptr (void) noexcept
    1326             :   {
    1327             :     return nullptr;
    1328             :   }
    1329             : 
    1330             :   PLUMED_GCH_NODISCARD constexpr
    1331             :   const value_ty *
    1332             :   get_inline_ptr (void) const noexcept
    1333             :   {
    1334             :     return nullptr;
    1335             :   }
    1336             : 
    1337             :   static constexpr
    1338             :   std::size_t
    1339             :   element_size (void) noexcept
    1340             :   {
    1341             :     return sizeof (value_ty);
    1342             :   }
    1343             : 
    1344             :   static constexpr
    1345             :   std::size_t
    1346             :   alignment (void) noexcept
    1347             :   {
    1348             :     return alignof (value_ty);
    1349             :   }
    1350             : 
    1351             :   static constexpr
    1352             :   unsigned
    1353             :   num_elements (void) noexcept
    1354             :   {
    1355             :     return 0;
    1356             :   }
    1357             : 
    1358             :   static constexpr
    1359             :   std::size_t
    1360             :   num_bytes (void) noexcept
    1361             :   {
    1362             :     return 0;
    1363             :   }
    1364             : };
    1365             : 
    1366             : template <typename Allocator, bool AvailableForEBO = std::is_empty<Allocator>::value
    1367             : #ifdef PLUMED_GCH_LIB_IS_FINAL
    1368             :           &&! std::is_final<Allocator>::value
    1369             : #endif // If you are using this with C++11 just don't use an allocator marked as final :P
    1370             :           >
    1371             : class allocator_inliner;
    1372             : 
    1373             : template <typename Allocator>
    1374             : class PLUMED_GCH_EMPTY_BASE allocator_inliner<Allocator, true>
    1375             : : private Allocator
    1376             : {
    1377             :   using alloc_traits = std::allocator_traits<Allocator>;
    1378             : 
    1379             :   static constexpr
    1380             :   bool
    1381             :   copy_assign_is_noop = ! alloc_traits::propagate_on_container_copy_assignment::value;
    1382             : 
    1383             :   static constexpr
    1384             :   bool
    1385             :   move_assign_is_noop = ! alloc_traits::propagate_on_container_move_assignment::value;
    1386             : 
    1387             :   static constexpr
    1388             :   bool
    1389             :   swap_is_noop = ! alloc_traits::propagate_on_container_swap::value;
    1390             : 
    1391             :   template <bool IsNoOp = copy_assign_is_noop,
    1392             :             typename std::enable_if<IsNoOp, bool>::type = true>
    1393             :   PLUMED_GCH_CPP20_CONSTEXPR
    1394             :   void
    1395             :   maybe_assign (const allocator_inliner&) noexcept { }
    1396             : 
    1397             :   template <bool IsNoOp = copy_assign_is_noop,
    1398             :             typename std::enable_if<! IsNoOp, bool>::type = false>
    1399             :   PLUMED_GCH_CPP20_CONSTEXPR
    1400             :   void
    1401             :   maybe_assign (const allocator_inliner& other)
    1402             :   noexcept (noexcept (std::declval<Allocator&> ().operator= (other)))
    1403             :   {
    1404             :     Allocator::operator= (other);
    1405             :   }
    1406             : 
    1407             :   template <bool IsNoOp = move_assign_is_noop,
    1408             :             typename std::enable_if<IsNoOp, bool>::type = true>
    1409             :   PLUMED_GCH_CPP20_CONSTEXPR
    1410             :   void
    1411             :   maybe_assign (allocator_inliner&&) noexcept { }
    1412             : 
    1413             :   template <bool IsNoOp = move_assign_is_noop,
    1414             :             typename std::enable_if<! IsNoOp, bool>::type = false>
    1415             :   PLUMED_GCH_CPP20_CONSTEXPR
    1416             :   void
    1417             :   maybe_assign (allocator_inliner&& other)
    1418             :   noexcept (noexcept (std::declval<Allocator&> ().operator= (std::move (other))))
    1419             :   {
    1420             :     Allocator::operator= (std::move (other));
    1421             :   }
    1422             : 
    1423             : public:
    1424             :   allocator_inliner            (void)                         = default;
    1425             :   allocator_inliner            (const allocator_inliner&)     = default;
    1426             :   allocator_inliner            (allocator_inliner&&) noexcept = default;
    1427             : //    allocator_inliner& operator= (const allocator_inliner&)     = impl;
    1428             : //    allocator_inliner& operator= (allocator_inliner&&) noexcept = impl;
    1429             :   ~allocator_inliner           (void)                         = default;
    1430             : 
    1431             :   constexpr explicit
    1432             :   allocator_inliner (const Allocator& alloc) noexcept
    1433             :     : Allocator (alloc)
    1434             :   { }
    1435             : 
    1436             :   PLUMED_GCH_CPP20_CONSTEXPR
    1437             :   allocator_inliner&
    1438             :   operator= (const allocator_inliner& other)
    1439             :   noexcept (noexcept (std::declval<allocator_inliner&> ().maybe_assign (other)))
    1440             :   {
    1441             :     assert (&other != this
    1442             :             &&  "`allocator_inliner` should not participate in self-copy-assignment.");
    1443             :     maybe_assign (other);
    1444             :     return *this;
    1445             :   }
    1446             : 
    1447             :   PLUMED_GCH_CPP20_CONSTEXPR
    1448             :   allocator_inliner&
    1449             :   operator= (allocator_inliner&& other)
    1450             :   noexcept (noexcept (std::declval<allocator_inliner&> ().maybe_assign (std::move (other))))
    1451             :   {
    1452             :     assert (&other != this
    1453             :             &&  "`allocator_inliner` should not participate in self-move-assignment.");
    1454             :     maybe_assign (std::move (other));
    1455             :     return *this;
    1456             :   }
    1457             : 
    1458             :   PLUMED_GCH_CPP14_CONSTEXPR
    1459             :   Allocator&
    1460             :   allocator_ref (void) noexcept
    1461             :   {
    1462             :     return *this;
    1463             :   }
    1464             : 
    1465             :   constexpr
    1466             :   const Allocator&
    1467             :   allocator_ref (void) const noexcept
    1468             :   {
    1469             :     return *this;
    1470             :   }
    1471             : 
    1472             :   template <bool IsNoOp = swap_is_noop,
    1473             :             typename std::enable_if<IsNoOp, bool>::type = true>
    1474             :   PLUMED_GCH_CPP20_CONSTEXPR
    1475             :   void
    1476             :   swap (allocator_inliner&)
    1477             :   { }
    1478             : 
    1479             :   template <bool IsNoOp = swap_is_noop,
    1480             :             typename std::enable_if<! IsNoOp, bool>::type = false>
    1481             :   PLUMED_GCH_CPP20_CONSTEXPR
    1482             :   void
    1483             :   swap (allocator_inliner& other)
    1484             :   {
    1485             :     using std::swap;
    1486             :     swap (static_cast<Allocator&> (*this), static_cast<Allocator&> (other));
    1487             :   }
    1488             : };
    1489             : 
    1490             : template <typename Allocator>
    1491             : class allocator_inliner<Allocator, false>
    1492             : {
    1493             :   using alloc_traits = std::allocator_traits<Allocator>;
    1494             : 
    1495             :   static constexpr
    1496             :   bool
    1497             :   copy_assign_is_noop = ! alloc_traits::propagate_on_container_copy_assignment::value;
    1498             : 
    1499             :   static constexpr
    1500             :   bool
    1501             :   move_assign_is_noop = ! alloc_traits::propagate_on_container_move_assignment::value;
    1502             : 
    1503             :   static constexpr
    1504             :   bool
    1505             :   swap_is_noop = ! alloc_traits::propagate_on_container_swap::value;
    1506             : 
    1507             :   template <bool IsNoOp = copy_assign_is_noop,
    1508             :             typename std::enable_if<IsNoOp, bool>::type = true>
    1509             :   PLUMED_GCH_CPP20_CONSTEXPR
    1510             :   void
    1511             :   maybe_assign (const allocator_inliner&) noexcept { }
    1512             : 
    1513             :   template <bool IsNoOp = copy_assign_is_noop,
    1514             :             typename std::enable_if<! IsNoOp, bool>::type = false>
    1515             :   PLUMED_GCH_CPP20_CONSTEXPR
    1516             :   void
    1517             :   maybe_assign (const allocator_inliner& other)
    1518             :   noexcept (noexcept (std::declval<decltype (other.m_alloc)&> () = other.m_alloc))
    1519             :   {
    1520             :     m_alloc = other.m_alloc;
    1521             :   }
    1522             : 
    1523             :   template <bool IsNoOp = move_assign_is_noop,
    1524             :             typename std::enable_if<IsNoOp, bool>::type = true>
    1525             :   PLUMED_GCH_CPP20_CONSTEXPR
    1526             :   void
    1527             :   maybe_assign (allocator_inliner&&) noexcept { }
    1528             : 
    1529             :   template <bool IsNoOp = move_assign_is_noop,
    1530             :             typename std::enable_if<! IsNoOp, bool>::type = false>
    1531             :   PLUMED_GCH_CPP20_CONSTEXPR
    1532             :   void
    1533             :   maybe_assign (allocator_inliner&& other)
    1534             :   noexcept (noexcept (std::declval<decltype (other.m_alloc)&> () = std::move (other.m_alloc)))
    1535             :   {
    1536             :     m_alloc = std::move (other.m_alloc);
    1537             :   }
    1538             : 
    1539             : public:
    1540             :   allocator_inliner            (void)                         = default;
    1541             :   allocator_inliner            (const allocator_inliner&)     = default;
    1542             :   allocator_inliner            (allocator_inliner&&) noexcept = default;
    1543             : //    allocator_inliner& operator= (const allocator_inliner&)     = impl;
    1544             : //    allocator_inliner& operator= (allocator_inliner&&) noexcept = impl;
    1545             :   ~allocator_inliner           (void)                         = default;
    1546             : 
    1547             :   PLUMED_GCH_CPP20_CONSTEXPR explicit
    1548             :   allocator_inliner (const Allocator& alloc) noexcept
    1549             :     : m_alloc (alloc)
    1550             :   { }
    1551             : 
    1552             :   PLUMED_GCH_CPP20_CONSTEXPR
    1553             :   allocator_inliner&
    1554             :   operator= (const allocator_inliner& other)
    1555             :   noexcept (noexcept (std::declval<allocator_inliner&> ().maybe_assign (other)))
    1556             :   {
    1557             :     assert (&other != this
    1558             :             &&  "`allocator_inliner` should not participate in self-copy-assignment.");
    1559             :     maybe_assign (other);
    1560             :     return *this;
    1561             :   }
    1562             : 
    1563             :   PLUMED_GCH_CPP20_CONSTEXPR
    1564             :   allocator_inliner&
    1565             :   operator= (allocator_inliner&& other)
    1566             :   noexcept (noexcept (std::declval<allocator_inliner&> ().maybe_assign (std::move (other))))
    1567             :   {
    1568             :     assert (&other != this
    1569             :             &&  "`allocator_inliner` should not participate in self-move-assignment.");
    1570             :     maybe_assign (std::move (other));
    1571             :     return *this;
    1572             :   }
    1573             : 
    1574             :   PLUMED_GCH_CPP14_CONSTEXPR
    1575             :   Allocator&
    1576             :   allocator_ref (void) noexcept
    1577             :   {
    1578             :     return m_alloc;
    1579             :   }
    1580             : 
    1581             :   constexpr
    1582             :   const Allocator&
    1583             :   allocator_ref (void) const noexcept
    1584             :   {
    1585             :     return m_alloc;
    1586             :   }
    1587             : 
    1588             :   template <bool IsNoOp = swap_is_noop,
    1589             :             typename std::enable_if<IsNoOp, bool>::type = true>
    1590             :   PLUMED_GCH_CPP20_CONSTEXPR
    1591             :   void
    1592             :   swap (allocator_inliner&)
    1593             :   { }
    1594             : 
    1595             :   template <bool IsNoOp = swap_is_noop,
    1596             :             typename std::enable_if<! IsNoOp, bool>::type = false>
    1597             :   PLUMED_GCH_CPP20_CONSTEXPR
    1598             :   void
    1599             :   swap (allocator_inliner& other)
    1600             :   {
    1601             :     using std::swap;
    1602             :     swap (m_alloc, other.m_alloc);
    1603             :   }
    1604             : 
    1605             : private:
    1606             :   Allocator m_alloc;
    1607             : };
    1608             : 
    1609             : template <typename Allocator>
    1610             : class PLUMED_GCH_EMPTY_BASE allocator_interface
    1611             : : public allocator_inliner<Allocator>
    1612             : {
    1613             : public:
    1614             :   template <typename, typename = void>
    1615             :   struct is_complete
    1616             : : std::false_type
    1617             :   { };
    1618             : 
    1619             :   template <typename U>
    1620             :   struct is_complete<U, decltype (static_cast<void> (sizeof (U)))>
    1621             : : std::true_type
    1622             :   { };
    1623             : 
    1624             :   using size_type = typename std::allocator_traits<Allocator>::size_type;
    1625             : 
    1626             :   // If difference_type is larger than size_type then we need
    1627             :   // to rectify that problem.
    1628             :   using difference_type = typename std::conditional<
    1629             :                           (
    1630             :                             static_cast<std::size_t> ((std::numeric_limits<size_type>::max) ())
    1631             :                             < // less-than
    1632             :                             static_cast<std::size_t> ((std::numeric_limits<
    1633             :                                 typename std::allocator_traits<Allocator>::difference_type>::max) ())
    1634             :                           ),
    1635             :                           typename std::make_signed<size_type>::type,
    1636             :                           typename std::allocator_traits<Allocator>::difference_type>::type;
    1637             : 
    1638             : private:
    1639             :   using alloc_base = allocator_inliner<Allocator>;
    1640             : 
    1641             : protected:
    1642             :   using alloc_ty     = Allocator;
    1643             :   using alloc_traits = std::allocator_traits<alloc_ty>;
    1644             :   using value_ty     = typename alloc_traits::value_type;
    1645             :   using ptr          = typename alloc_traits::pointer;
    1646             :   using cptr         = typename alloc_traits::const_pointer;
    1647             :   using vptr         = typename alloc_traits::void_pointer;
    1648             :   using cvptr        = typename alloc_traits::const_void_pointer;
    1649             : 
    1650             :   // Select the fastest types larger than the user-facing types. These are only intended for
    1651             :   // internal computations, and should not have any memory footprint visible to consumers.
    1652             :   using size_ty =
    1653             :     typename std::conditional<
    1654             :     (sizeof (size_type) <= sizeof (std::uint8_t)),
    1655             :     std::uint_fast8_t,
    1656             :     typename std::conditional<
    1657             :     (sizeof (size_type) <= sizeof (std::uint16_t)),
    1658             :     std::uint_fast16_t,
    1659             :     typename std::conditional<
    1660             :     (sizeof (size_type) <= sizeof (std::uint32_t)),
    1661             :     std::uint_fast32_t,
    1662             :     typename std::conditional<
    1663             :     (sizeof (size_type) <= sizeof (std::uint64_t)),
    1664             :     std::uint_fast64_t,
    1665             :     size_type
    1666             :     >::type
    1667             :     >::type
    1668             :     >::type
    1669             :     >::type;
    1670             : 
    1671             :   using diff_ty =
    1672             :     typename std::conditional<
    1673             :     (sizeof (difference_type) <= sizeof (std::int8_t)),
    1674             :     std::int_fast8_t,
    1675             :     typename std::conditional<
    1676             :     (sizeof (difference_type) <= sizeof (std::int16_t)),
    1677             :     std::int_fast16_t,
    1678             :     typename std::conditional<
    1679             :     (sizeof (difference_type) <= sizeof (std::int32_t)),
    1680             :     std::int_fast32_t,
    1681             :     typename std::conditional<
    1682             :     (sizeof (difference_type) <= sizeof (std::int64_t)),
    1683             :     std::int_fast64_t,
    1684             :     difference_type
    1685             :     >::type
    1686             :     >::type
    1687             :     >::type
    1688             :     >::type;
    1689             : 
    1690             :   using alloc_base::allocator_ref;
    1691             : 
    1692             : private:
    1693             :   template <typename ...>
    1694             :   using void_t = void;
    1695             : 
    1696             :   template <bool B>
    1697             :   using bool_constant = std::integral_constant<bool, B>;
    1698             : 
    1699             :   template <typename V, typename Enable = void>
    1700             :   struct is_trivially_destructible
    1701             : : std::false_type
    1702             :   { };
    1703             : 
    1704             :   template <typename V>
    1705             :   struct is_trivially_destructible<V, typename std::enable_if<is_complete<V>::value>::type>
    1706             : : std::is_trivially_destructible<V>
    1707             :   { };
    1708             : 
    1709             :   template <typename Void, typename T, typename ...Args>
    1710             :   struct is_trivially_constructible_impl
    1711             : : std::false_type
    1712             :   { };
    1713             : 
    1714             :   template <typename V, typename ...Args>
    1715             :   struct is_trivially_constructible_impl<
    1716             :     typename std::enable_if<is_complete<V>::value>::type,
    1717             :     V, Args...>
    1718             : : std::is_trivially_constructible<V, Args...>
    1719             :   { };
    1720             : 
    1721             :   template <typename V, typename ...Args>
    1722             :   struct is_trivially_constructible
    1723             : : is_trivially_constructible_impl<void, V, Args...>
    1724             :   { };
    1725             : 
    1726             :   template <typename T, typename Enable = void>
    1727             :   struct underlying_if_enum
    1728             :   {
    1729             :     using type = T;
    1730             :   };
    1731             : 
    1732             :   template <typename T>
    1733             :   struct underlying_if_enum<T, typename std::enable_if<std::is_enum<T>::value>::type>
    1734             : : std::underlying_type<T>
    1735             :   { };
    1736             : 
    1737             :   template <typename T>
    1738             :   using underlying_if_enum_t = typename underlying_if_enum<T>::type;
    1739             : 
    1740             :   template <typename, typename = void>
    1741             :   struct has_ptr_traits_to_address
    1742             : : std::false_type
    1743             :   { };
    1744             : 
    1745             :   template <typename P>
    1746             :   struct has_ptr_traits_to_address<P,
    1747             :                                    void_t<decltype (std::pointer_traits<P>::to_address (std::declval<P> ()))>>
    1748             : : std::true_type
    1749             :   { };
    1750             : 
    1751             :   template <typename Void, typename A, typename V, typename ...Args>
    1752             :   struct has_alloc_construct_check
    1753             : : std::false_type
    1754             :   { };
    1755             : 
    1756             :   template <typename A, typename V, typename ...Args>
    1757             :   struct has_alloc_construct_check<
    1758             :     void_t<decltype (std::declval<A&> ().construct (std::declval<V *> (),
    1759             :                      std::declval<Args> ()...))>,
    1760             :     A, V, Args...>
    1761             : : std::true_type
    1762             :   { };
    1763             : 
    1764             :   template <typename Void, typename A, typename V, typename ...Args>
    1765             :   struct has_alloc_construct_impl
    1766             : : std::false_type
    1767             :   { };
    1768             : 
    1769             :   template <typename A, typename V, typename ...Args>
    1770             :   struct has_alloc_construct_impl<typename std::enable_if<is_complete<V>::value>::type,
    1771             :                                   A, V, Args...>
    1772             : : has_alloc_construct_check<void, A, V, Args...>
    1773             :   { };
    1774             : 
    1775             :   template <typename A, typename V, typename ...Args>
    1776             :   struct has_alloc_construct
    1777             : : has_alloc_construct_impl<void, A, V, Args...>
    1778             :   { };
    1779             : 
    1780             :   template <typename A, typename V, typename ...Args>
    1781             :   struct must_use_alloc_construct
    1782             : : bool_constant<! std::is_same<A, std::allocator<V>>::value
    1783             :                   &&  has_alloc_construct<A, V, Args...>::value>
    1784             :   { };
    1785             : 
    1786             :   template <typename Void, typename A, typename V>
    1787             :   struct has_alloc_destroy_impl
    1788             : : std::false_type
    1789             :   { };
    1790             : 
    1791             :   template <typename A, typename V>
    1792             :   struct has_alloc_destroy_impl<
    1793             :     void_t<decltype (std::declval<A&> ().destroy (std::declval<V *> ()))>,
    1794             :     A, V>
    1795             : : std::true_type
    1796             :   { };
    1797             : 
    1798             :   template <typename A, typename V, typename Enable = void>
    1799             :   struct has_alloc_destroy
    1800             : : std::false_type
    1801             :   { };
    1802             : 
    1803             :   template <typename A, typename V>
    1804             :   struct has_alloc_destroy<A, V, typename std::enable_if<is_complete<V>::value>::type>
    1805             : : has_alloc_destroy_impl<void, A, V>
    1806             :   { };
    1807             : 
    1808             :   template <typename A, typename V>
    1809             :   struct must_use_alloc_destroy
    1810             : : bool_constant<! std::is_same<A, std::allocator<V>>::value
    1811             :                   &&  has_alloc_destroy<A, V>::value>
    1812             :   { };
    1813             : 
    1814             : public:
    1815             :   allocator_interface (void)                           = default;
    1816             : //    allocator_interface (const allocator_interface&)     = impl;
    1817             :   allocator_interface (allocator_interface&&) noexcept = default;
    1818             : 
    1819             :   PLUMED_GCH_CPP20_CONSTEXPR
    1820             :   allocator_interface&
    1821             :   operator= (const allocator_interface&) = default;
    1822             : 
    1823             :   PLUMED_GCH_CPP20_CONSTEXPR
    1824             :   allocator_interface&
    1825             :   operator= (allocator_interface&&) noexcept = default;
    1826             : 
    1827             :   ~allocator_interface (void) = default;
    1828             : 
    1829             :   PLUMED_GCH_CPP20_CONSTEXPR
    1830             :   allocator_interface (const allocator_interface& other) noexcept
    1831             :     : alloc_base (alloc_traits::select_on_container_copy_construction (other.allocator_ref ()))
    1832             :   { }
    1833             : 
    1834             :   constexpr explicit
    1835             :   allocator_interface (const alloc_ty& alloc) noexcept
    1836             :     : alloc_base (alloc)
    1837             :   { }
    1838             : 
    1839             :   template <typename T>
    1840             :   constexpr explicit
    1841             :   allocator_interface (T&&, const alloc_ty& alloc) noexcept
    1842             :     : allocator_interface (alloc)
    1843             :   { }
    1844             : 
    1845             :   template <typename, typename, typename = void>
    1846             :   struct is_memcpyable_integral
    1847             : : std::false_type
    1848             :   { };
    1849             : 
    1850             :   template <typename From, typename To>
    1851             :   struct is_memcpyable_integral<From, To,
    1852             :                                 typename std::enable_if<is_complete<From>::value>::type>
    1853             :   {
    1854             :     using from = underlying_if_enum_t<From>;
    1855             :     using to   = underlying_if_enum_t<To>;
    1856             : 
    1857             :     static constexpr
    1858             :     bool
    1859             :     value = (sizeof (from) == sizeof (to))
    1860             :     &&  (std::is_same<bool, from>::value == std::is_same<bool, to>::value)
    1861             :     &&  std::is_integral<from>::value
    1862             :     &&  std::is_integral<to>::value;
    1863             :                         };
    1864             : 
    1865             :   template <typename From, typename To>
    1866             :   struct is_convertible_pointer
    1867             : : bool_constant<std::is_pointer<From>::value
    1868             :                   &&  std::is_pointer<To>::value
    1869             :                   &&  std::is_convertible<From, To>::value>
    1870             :   { };
    1871             : 
    1872             :   // Memcpyable assignment.
    1873             :   template <typename QualifiedFrom, typename QualifiedTo = value_ty, typename Enable = void>
    1874             :   struct is_memcpyable
    1875             : : std::false_type
    1876             :   { };
    1877             : 
    1878             :   template <typename QualifiedFrom, typename QualifiedTo>
    1879             :   struct is_memcpyable<QualifiedFrom, QualifiedTo,
    1880             :                        typename std::enable_if<is_complete<QualifiedFrom>::value>::type>
    1881             :   {
    1882             :     static_assert (! std::is_reference<QualifiedTo>::value,
    1883             :                    "QualifiedTo must not be a reference.");
    1884             : 
    1885             :     using from = typename std::remove_reference<
    1886             :       typename std::remove_cv<QualifiedFrom>::type>::type;
    1887             : 
    1888             :     using to = typename std::remove_cv<QualifiedTo>::type;
    1889             : 
    1890             :     static constexpr
    1891             :     bool
    1892             :     value = std::is_trivially_assignable<QualifiedTo&, QualifiedFrom>::value
    1893             :     &&  std::is_trivially_copyable<to>::value
    1894             :     &&  (  std::is_same<typename std::remove_cv<from>::type, to>::value
    1895             :            ||  is_memcpyable_integral<from, to>::value
    1896             :            ||  is_convertible_pointer<from, to>::value);
    1897             :                                      };
    1898             : 
    1899             :   // Memcpyable construction.
    1900             :   template <typename QualifiedFrom, typename QualifiedTo>
    1901             :   struct is_uninitialized_memcpyable_impl
    1902             :   {
    1903             :     static_assert (! std::is_reference<QualifiedTo>::value,
    1904             :                    "QualifiedTo must not be a reference.");
    1905             : 
    1906             :     using from = typename std::remove_reference<
    1907             :       typename std::remove_cv<QualifiedFrom>::type>::type;
    1908             : 
    1909             :     using to = typename std::remove_cv<QualifiedTo>::type;
    1910             : 
    1911             :     static constexpr
    1912             :     bool
    1913             :     value = std::is_trivially_constructible<QualifiedTo, QualifiedFrom>::value
    1914             :     &&  std::is_trivially_copyable<to>::value
    1915             :     &&  (  std::is_same<typename std::remove_cv<from>::type, to>::value
    1916             :            ||  is_memcpyable_integral<from, to>::value
    1917             :            ||  is_convertible_pointer<from, to>::value)
    1918             :     &&  (! must_use_alloc_construct<alloc_ty, value_ty, from>::value
    1919             :          &&! must_use_alloc_destroy<alloc_ty, value_ty>::value);
    1920             :                                    };
    1921             : 
    1922             :   template <typename To, typename ...Args>
    1923             :   struct is_uninitialized_memcpyable
    1924             : : std::false_type
    1925             :   { };
    1926             : 
    1927             :   template <typename To, typename From>
    1928             :   struct is_uninitialized_memcpyable<To, From>
    1929             : : is_uninitialized_memcpyable_impl<From, To>
    1930             :   { };
    1931             : 
    1932             :   template <typename Iterator>
    1933             :   struct is_small_vector_iterator
    1934             : : std::false_type
    1935             :   { };
    1936             : 
    1937             :   template <typename ...Ts>
    1938             :   struct is_small_vector_iterator<small_vector_iterator<Ts...>>
    1939             : : std::true_type
    1940             :   { };
    1941             : 
    1942             :   template <typename InputIt>
    1943             :   struct is_contiguous_iterator
    1944             : : bool_constant<
    1945             :     std::is_same<InputIt, ptr>::value
    1946             :     ||  std::is_same<InputIt, cptr>::value
    1947             :     ||  is_small_vector_iterator<InputIt>::value
    1948             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    1949             :     ||  std::contiguous_iterator<InputIt>
    1950             : #endif
    1951             : #ifdef PLUMED_GCH_STDLIB_INTEROP
    1952             :     ||  std::is_same<InputIt, typename std::array<value_ty>::iterator>::value
    1953             :     ||  std::is_same<InputIt, typename std::array<value_ty>::const_iterator>::value
    1954             :     ||  (! std::is_same<value_ty, bool>
    1955             :          &&  (  std::is_same<InputIt, typename std::vector<value_ty>::iterator>::value
    1956             :                 ||  std::is_same<InputIt, typename std::vector<value_ty>::const_iterator>::value)
    1957             :                                 )
    1958             :     ||  std::is_same<InputIt,
    1959             :                      decltype (std::begin (std::declval<std::valarray<value_ty>&> ()))>::value
    1960             :     ||  std::is_same<InputIt,
    1961             :                      decltype (std::begin (std::declval<const std::valarray<value_ty>&> ()))>::value
    1962             : #endif
    1963             :     >
    1964             :   { };
    1965             : 
    1966             :   template <typename InputIt>
    1967             :   struct is_memcpyable_iterator
    1968             : : bool_constant<is_memcpyable<decltype (*std::declval<InputIt> ())>::value
    1969             :                   &&  is_contiguous_iterator<InputIt>::value>
    1970             :   { };
    1971             : 
    1972             :   // Unwrap `move_iterator`s.
    1973             :   template <typename InputIt>
    1974             :   struct is_memcpyable_iterator<std::move_iterator<InputIt>>
    1975             : : is_memcpyable_iterator<InputIt>
    1976             :   { };
    1977             : 
    1978             :   template <typename InputIt, typename V = value_ty>
    1979             :   struct is_uninitialized_memcpyable_iterator
    1980             : : bool_constant<is_uninitialized_memcpyable<V, decltype (*std::declval<InputIt> ())>::value
    1981             :                   &&  is_contiguous_iterator<InputIt>::value>
    1982             :   { };
    1983             : 
    1984             :   // unwrap move_iterators
    1985             :   template <typename U, typename V>
    1986             :   struct is_uninitialized_memcpyable_iterator<std::move_iterator<U>, V>
    1987             : : is_uninitialized_memcpyable_iterator<U, V>
    1988             :   { };
    1989             : 
    1990             :   PLUMED_GCH_NORETURN
    1991             :   static PLUMED_GCH_CPP20_CONSTEXPR
    1992             :   void
    1993             :   throw_range_length_error (void)
    1994             :   {
    1995             : #ifdef PLUMED_GCH_EXCEPTIONS
    1996             :     throw std::length_error ("The specified range is too long.");
    1997             : #else
    1998             :     std::fprintf (stderr, "[gch::small_vector] The specified range is too long.");
    1999             :     std::abort ();
    2000             : #endif
    2001             :   }
    2002             : 
    2003             :   static constexpr
    2004             :   value_ty *
    2005             :   to_address (value_ty *p) noexcept
    2006             :   {
    2007             :     static_assert (! std::is_function<value_ty>::value, "value_ty is a function pointer.");
    2008             :     return p;
    2009             :   }
    2010             : 
    2011             :   static constexpr
    2012             :   const value_ty *
    2013             :   to_address (const value_ty *p) noexcept
    2014             :   {
    2015             :     static_assert (! std::is_function<value_ty>::value, "value_ty is a function pointer.");
    2016             :     return p;
    2017             :   }
    2018             : 
    2019             :   template <typename Pointer,
    2020             :             typename std::enable_if<has_ptr_traits_to_address<Pointer>::value>::type * = nullptr>
    2021             :   static constexpr
    2022             :   auto
    2023             :   to_address (const Pointer& p) noexcept
    2024             :   -> decltype (std::pointer_traits<Pointer>::to_address (p))
    2025             :   {
    2026             :     return std::pointer_traits<Pointer>::to_address (p);
    2027             :   }
    2028             : 
    2029             :   template <typename Pointer,
    2030             :             typename std::enable_if<! has_ptr_traits_to_address<Pointer>::value>::type * = nullptr>
    2031             :   static constexpr
    2032             :   auto
    2033             :   to_address (const Pointer& p) noexcept
    2034             :   -> decltype (to_address (p.operator-> ()))
    2035             :   {
    2036             :     return to_address (p.operator-> ());
    2037             :   }
    2038             : 
    2039             :   template <typename Integer>
    2040             :   PLUMED_GCH_NODISCARD
    2041             :   static PLUMED_GCH_CONSTEVAL
    2042             :   std::size_t
    2043             :   numeric_max (void) noexcept
    2044             :   {
    2045             :     static_assert (0 <= (std::numeric_limits<Integer>::max) (), "Integer is nonpositive.");
    2046             :     return static_cast<std::size_t> ((std::numeric_limits<Integer>::max) ());
    2047             :   }
    2048             : 
    2049             :   PLUMED_GCH_NODISCARD
    2050             :   static PLUMED_GCH_CPP17_CONSTEXPR
    2051             :   size_ty
    2052             :   internal_range_length (cptr first, cptr last) noexcept
    2053             :   {
    2054             :     // This is guaranteed to be less than or equal to max size_ty.
    2055             :     return static_cast<size_ty> (last - first);
    2056             :   }
    2057             : 
    2058             :   template <typename RandomIt>
    2059             :   PLUMED_GCH_NODISCARD
    2060             :   static PLUMED_GCH_CPP17_CONSTEXPR
    2061             :   size_ty
    2062             :   external_range_length_impl (RandomIt first, RandomIt last, std::random_access_iterator_tag)
    2063             :   {
    2064             :     assert (0 <= (last - first) && "Invalid range.");
    2065             :     const auto len = static_cast<std::size_t> (last - first);
    2066             : #ifndef NDEBUG
    2067             :     if (numeric_max<size_ty> () < len)
    2068             :       throw_range_length_error ();
    2069             : #endif
    2070             :     return static_cast<size_ty> (len);
    2071             :   }
    2072             : 
    2073             :   template <typename ForwardIt>
    2074             :   PLUMED_GCH_NODISCARD
    2075             :   static PLUMED_GCH_CPP17_CONSTEXPR
    2076             :   size_ty
    2077             :   external_range_length_impl (ForwardIt first, ForwardIt last, std::forward_iterator_tag)
    2078             :   {
    2079             : #ifdef PLUMED_GCH_LIB_IS_CONSTANT_EVALUATED
    2080             :     if (std::is_constant_evaluated ())
    2081             :     {
    2082             :       // Make sure constexpr doesn't get broken by `using namespace std::rel_ops`.
    2083             :       typename std::iterator_traits<ForwardIt>::difference_type len = 0;
    2084             :       for (; ! (first == last); ++first)
    2085             :         ++len;
    2086             :       assert (static_cast<std::size_t> (len) <= numeric_max<size_ty> ());
    2087             :       return static_cast<size_ty> (len);
    2088             :     }
    2089             : #endif
    2090             : 
    2091             :     const auto len = static_cast<std::size_t> (std::distance (first, last));
    2092             : #ifndef NDEBUG
    2093             :     if (numeric_max<size_ty> () < len)
    2094             :       throw_range_length_error ();
    2095             : #endif
    2096             :     return static_cast<size_ty> (len);
    2097             :   }
    2098             : 
    2099             :   template <typename ForwardIt,
    2100             :             typename ItDiffT = typename std::iterator_traits<ForwardIt>::difference_type,
    2101             :             typename std::enable_if<(numeric_max<size_ty> () < numeric_max<ItDiffT> ()),
    2102             :                                      bool>::type = true>
    2103             :             PLUMED_GCH_NODISCARD
    2104             :             static PLUMED_GCH_CPP17_CONSTEXPR
    2105             :             size_ty
    2106             :             external_range_length (ForwardIt first, ForwardIt last)
    2107             :   {
    2108             :     using iterator_cat = typename std::iterator_traits<ForwardIt>::iterator_category;
    2109             :     return external_range_length_impl (first, last, iterator_cat { });
    2110             :   }
    2111             : 
    2112             :   template <typename ForwardIt,
    2113             :             typename ItDiffT = typename std::iterator_traits<ForwardIt>::difference_type,
    2114             :             typename std::enable_if<! (numeric_max<size_ty> () < numeric_max<ItDiffT> ()),
    2115             :                                        bool>::type = false>
    2116             :             PLUMED_GCH_NODISCARD
    2117             :             static PLUMED_GCH_CPP17_CONSTEXPR
    2118             :             size_ty
    2119             :             external_range_length (ForwardIt first, ForwardIt last) noexcept
    2120             :   {
    2121             : #ifdef PLUMED_GCH_LIB_IS_CONSTANT_EVALUATED
    2122             :     if (std::is_constant_evaluated ())
    2123             :     {
    2124             :       // Make sure constexpr doesn't get broken by `using namespace std::rel_ops`.
    2125             :       size_ty len = 0;
    2126             :       for (; ! (first == last); ++first)
    2127             :         ++len;
    2128             :       return len;
    2129             :     }
    2130             : #endif
    2131             : 
    2132       24025 :     return static_cast<size_ty> (std::distance (first, last));
    2133             :   }
    2134             : 
    2135             :   template <typename Iterator,
    2136             :             typename IteratorDiffT = typename std::iterator_traits<Iterator>::difference_type,
    2137             :             typename Integer = IteratorDiffT>
    2138             :   PLUMED_GCH_NODISCARD
    2139             :   static PLUMED_GCH_CPP17_CONSTEXPR
    2140             :   Iterator
    2141             :   unchecked_next (Iterator pos, Integer n = 1) noexcept
    2142             :   {
    2143    20969311 :     unchecked_advance (pos, static_cast<IteratorDiffT> (n));
    2144    20993336 :     return pos;
    2145             :   }
    2146             : 
    2147             :   template <typename Iterator,
    2148             :             typename IteratorDiffT = typename std::iterator_traits<Iterator>::difference_type,
    2149             :             typename Integer = IteratorDiffT>
    2150             :   PLUMED_GCH_NODISCARD
    2151             :   static PLUMED_GCH_CPP17_CONSTEXPR
    2152             :   Iterator
    2153             :   unchecked_prev (Iterator pos, Integer n = 1) noexcept
    2154             :   {
    2155             :     unchecked_advance (pos, -static_cast<IteratorDiffT> (n));
    2156     2149600 :     return pos;
    2157             :   }
    2158             : 
    2159             :   template <typename Iterator,
    2160             :             typename IteratorDiffT = typename std::iterator_traits<Iterator>::difference_type,
    2161             :             typename Integer = IteratorDiffT>
    2162             :   static PLUMED_GCH_CPP17_CONSTEXPR
    2163             :   void
    2164             :   unchecked_advance (Iterator& pos, Integer n) noexcept
    2165             :   {
    2166             :     std::advance (pos, static_cast<IteratorDiffT> (n));
    2167             :   }
    2168             : 
    2169             :   PLUMED_GCH_NODISCARD PLUMED_GCH_CPP20_CONSTEXPR
    2170             :   size_ty
    2171             :   get_max_size (void) const noexcept
    2172             :   {
    2173             :     // This is protected from max/min macros.
    2174             :     return (std::min) (static_cast<size_ty> (alloc_traits::max_size (allocator_ref ())),
    2175             :                        static_cast<size_ty> (numeric_max<difference_type> ()));
    2176             :   }
    2177             : 
    2178             :   PLUMED_GCH_NODISCARD PLUMED_GCH_CPP20_CONSTEXPR
    2179             :   ptr
    2180             :   allocate (size_ty n)
    2181             :   {
    2182             :     return alloc_traits::allocate (allocator_ref (), static_cast<size_type> (n));
    2183             :   }
    2184             : 
    2185             :   PLUMED_GCH_NODISCARD PLUMED_GCH_CPP20_CONSTEXPR
    2186             :   ptr
    2187             :   allocate_with_hint (size_ty n, cptr hint)
    2188             :   {
    2189             :     return alloc_traits::allocate (allocator_ref (), static_cast<size_type> (n), hint);
    2190             :   }
    2191             : 
    2192             :   PLUMED_GCH_CPP20_CONSTEXPR
    2193             :   void
    2194             :   deallocate (ptr p, size_ty n)
    2195             :   {
    2196             :     alloc_traits::deallocate (allocator_ref (), to_address (p),
    2197             :                               static_cast<size_type> (n));
    2198        3657 :   }
    2199             : 
    2200             :   template <typename U,
    2201             :             typename std::enable_if<
    2202             :               is_uninitialized_memcpyable<value_ty, U>::value>::type * = nullptr>
    2203             :   PLUMED_GCH_CPP20_CONSTEXPR
    2204             :   void
    2205             :   construct (ptr p, U&& val) noexcept
    2206             :   {
    2207             : #ifdef PLUMED_GCH_LIB_IS_CONSTANT_EVALUATED
    2208             :     if (std::is_constant_evaluated ())
    2209             :     {
    2210             :       alloc_traits::construct (allocator_ref (), to_address (p), std::forward<U> (val));
    2211             :       return;
    2212             :     }
    2213             : #endif
    2214             :     std::memcpy (to_address (p), &val, sizeof (value_ty));
    2215             :   }
    2216             : 
    2217             :   // basically alloc_traits::construct
    2218             :   // all this is so we can replicate C++20 behavior in the other overload
    2219             :   template <typename A = alloc_ty, typename V = value_ty, typename ...Args,
    2220             :             typename std::enable_if<(  sizeof...(Args) != 1
    2221             :                                        ||! is_uninitialized_memcpyable<V, Args...>::value)
    2222             :                                     &&  has_alloc_construct<A, V, Args...>::value>::type * = nullptr>
    2223             :   PLUMED_GCH_CPP20_CONSTEXPR
    2224             :   void
    2225             :   construct (ptr p, Args&&... args)
    2226             :   noexcept (noexcept (alloc_traits::construct (std::declval<alloc_ty&> (),
    2227             :                       std::declval<value_ty *> (),
    2228             :                       std::forward<Args> (args)...)))
    2229             :   {
    2230             :     alloc_traits::construct (allocator_ref (), to_address (p), std::forward<Args> (args)...);
    2231             :   }
    2232             : 
    2233             :   template <typename A = alloc_ty, typename V = value_ty, typename ...Args,
    2234             :             void_t<typename std::enable_if<(  sizeof...(Args) != 1
    2235             :                    ||! is_uninitialized_memcpyable<V, Args...>::value)
    2236             :                    &&! has_alloc_construct<A, V, Args...>::value>::type,
    2237             :                    decltype (::new (std::declval<void *> ()) V (std::declval<Args> ()...))
    2238             :                    > * = nullptr>
    2239             :   PLUMED_GCH_CPP20_CONSTEXPR
    2240             :   void
    2241             :   construct (ptr p, Args&&... args)
    2242             :   noexcept (noexcept (::new (std::declval<void *> ()) value_ty (std::declval<Args> ()...)))
    2243             :   {
    2244             :     construct_at (to_address (p), std::forward<Args> (args)...);
    2245             :   }
    2246             : 
    2247             :   template <typename A = alloc_ty, typename V = value_ty,
    2248             :             typename std::enable_if<is_trivially_destructible<V>::value
    2249             :                                     &&! must_use_alloc_destroy<A, V>::value>::type * = nullptr>
    2250             :   PLUMED_GCH_CPP20_CONSTEXPR
    2251             :   void
    2252             :   destroy (ptr) const noexcept
    2253             :   { }
    2254             : 
    2255             :   template <typename A = alloc_ty, typename V = value_ty,
    2256             :             typename std::enable_if<(! is_trivially_destructible<V>::value
    2257             :                                      ||  must_use_alloc_destroy<A, V>::value)
    2258             :                                     &&  has_alloc_destroy<A, V>::value>::type * = nullptr>
    2259             :   PLUMED_GCH_CPP20_CONSTEXPR
    2260             :   void
    2261             :   destroy (ptr p) noexcept
    2262             :   {
    2263             :     alloc_traits::destroy (allocator_ref (), to_address (p));
    2264             :   }
    2265             : 
    2266             :   // defined so we match C++20 behavior in all cases.
    2267             :   template <typename A = alloc_ty, typename V = value_ty,
    2268             :             typename std::enable_if<(! is_trivially_destructible<V>::value
    2269             :                                      ||  must_use_alloc_destroy<A, V>::value)
    2270             :                                     &&! has_alloc_destroy<A, V>::value>::type * = nullptr>
    2271             :   PLUMED_GCH_CPP20_CONSTEXPR
    2272             :   void
    2273             :   destroy (ptr p) noexcept
    2274             :   {
    2275             :     destroy_at (to_address (p));
    2276             :   }
    2277             : 
    2278             :   template <typename A = alloc_ty, typename V = value_ty,
    2279             :             typename std::enable_if<is_trivially_destructible<V>::value
    2280             :                                     &&! must_use_alloc_destroy<A, V>::value>::type * = nullptr>
    2281             :   PLUMED_GCH_CPP14_CONSTEXPR
    2282             :   void
    2283             :   destroy_range (ptr, ptr) const noexcept
    2284             :   { }
    2285             : 
    2286             :   template <typename A = alloc_ty, typename V = value_ty,
    2287             :             typename std::enable_if<! is_trivially_destructible<V>::value
    2288             :                                     ||  must_use_alloc_destroy<A, V>::value>::type * = nullptr>
    2289             :   PLUMED_GCH_CPP20_CONSTEXPR
    2290             :   void
    2291             :   destroy_range (ptr first, ptr last) noexcept
    2292             :   {
    2293             :     for (; ! (first == last); ++first)
    2294             :       destroy (first);
    2295             :   }
    2296             : 
    2297             :   // allowed if trivially copyable and we use the standard allocator
    2298             :   // and InputIt is a contiguous iterator
    2299             :   template <typename ForwardIt,
    2300             :             typename std::enable_if<
    2301             :               is_uninitialized_memcpyable_iterator<ForwardIt>::value, bool>::type = true>
    2302             :   PLUMED_GCH_CPP20_CONSTEXPR
    2303             :   ptr
    2304       24025 :   uninitialized_copy (ForwardIt first, ForwardIt last, ptr dest) noexcept
    2305             :   {
    2306             :     static_assert (std::is_constructible<value_ty, decltype (*first)>::value,
    2307             :                    "`value_type` must be copy constructible.");
    2308             : 
    2309             : #ifdef PLUMED_GCH_LIB_IS_CONSTANT_EVALUATED
    2310             :     if (std::is_constant_evaluated ())
    2311             :       return default_uninitialized_copy (first, last, dest);
    2312             : #endif
    2313             : 
    2314             :     const size_ty num_copy = external_range_length (first, last);
    2315       24025 :     if (num_copy != 0)
    2316       21681 :       std::memcpy (to_address (dest), to_address (first), num_copy * sizeof (value_ty));
    2317       24025 :     return unchecked_next (dest, num_copy);
    2318             :   }
    2319             : 
    2320             :   template <typename ForwardIt,
    2321             :             typename std::enable_if<
    2322             :               is_uninitialized_memcpyable_iterator<ForwardIt>::value, bool>::type = true>
    2323             :   PLUMED_GCH_CPP20_CONSTEXPR
    2324             :   ptr
    2325             :   uninitialized_copy (std::move_iterator<ForwardIt> first,
    2326             :                       std::move_iterator<ForwardIt> last,
    2327             :                       ptr dest) noexcept
    2328             :   {
    2329        3657 :     return uninitialized_copy (first.base (), last.base (), dest);
    2330             :   }
    2331             : 
    2332             :   template <typename InputIt,
    2333             :             typename std::enable_if<
    2334             :               ! is_uninitialized_memcpyable_iterator<InputIt>::value, bool>::type = false>
    2335             :   PLUMED_GCH_CPP20_CONSTEXPR
    2336             :   ptr
    2337             :   uninitialized_copy (InputIt first, InputIt last, ptr d_first)
    2338             :   {
    2339             :     return default_uninitialized_copy (first, last, d_first);
    2340             :   }
    2341             : 
    2342             :   template <typename InputIt>
    2343             :   PLUMED_GCH_CPP20_CONSTEXPR
    2344             :   ptr
    2345             :   default_uninitialized_copy (InputIt first, InputIt last, ptr d_first)
    2346             :   {
    2347             :     ptr d_last = d_first;
    2348             :     PLUMED_GCH_TRY
    2349             :     {
    2350             :       // Note: Not != because `using namespace std::rel_ops` can break constexpr.
    2351             :       for (; ! (first == last); ++first, static_cast<void> (++d_last))
    2352             :         construct (d_last, *first);
    2353             :       return d_last;
    2354             :     }
    2355             :     PLUMED_GCH_CATCH (...)
    2356             :     {
    2357             :       destroy_range (d_first, d_last);
    2358             :       PLUMED_GCH_THROW;
    2359             :     }
    2360             :   }
    2361             : 
    2362             :   template <typename A = alloc_ty, typename V = value_ty,
    2363             :             typename std::enable_if<is_trivially_constructible<V>::value
    2364             :                                     &&! must_use_alloc_construct<A, V>::value>::type * = nullptr>
    2365             :   PLUMED_GCH_CPP20_CONSTEXPR
    2366             :   ptr
    2367             :   uninitialized_value_construct (ptr first, ptr last)
    2368             :   {
    2369             : #ifdef PLUMED_GCH_LIB_IS_CONSTANT_EVALUATED
    2370             :     if (std::is_constant_evaluated ())
    2371             :       return default_uninitialized_value_construct (first, last);
    2372             : #endif
    2373             :     std::fill (first, last, value_ty ());
    2374             :     return last;
    2375             :   }
    2376             : 
    2377             :   template <typename A = alloc_ty, typename V = value_ty,
    2378             :             typename std::enable_if<! is_trivially_constructible<V>::value
    2379             :                                     ||  must_use_alloc_construct<A, V>::value>::type * = nullptr>
    2380             :   PLUMED_GCH_CPP20_CONSTEXPR
    2381             :   ptr
    2382             :   uninitialized_value_construct (ptr first, ptr last)
    2383             :   {
    2384             :     return default_uninitialized_value_construct (first, last);
    2385             :   }
    2386             : 
    2387             :   PLUMED_GCH_CPP20_CONSTEXPR
    2388             :   ptr
    2389             :   default_uninitialized_value_construct (ptr first, ptr last)
    2390             :   {
    2391             :     ptr curr = first;
    2392             :     PLUMED_GCH_TRY
    2393             :     {
    2394             :       for (; ! (curr == last); ++curr)
    2395             :         construct (curr);
    2396             :       return curr;
    2397             :     }
    2398             :     PLUMED_GCH_CATCH (...)
    2399             :     {
    2400             :       destroy_range (first, curr);
    2401             :       PLUMED_GCH_THROW;
    2402             :     }
    2403             :   }
    2404             : 
    2405             :   PLUMED_GCH_CPP20_CONSTEXPR
    2406             :   ptr
    2407             :   uninitialized_fill (ptr first, ptr last)
    2408             :   {
    2409             :     return uninitialized_value_construct (first, last);
    2410             :   }
    2411             : 
    2412             :   PLUMED_GCH_CPP20_CONSTEXPR
    2413             :   ptr
    2414             :   uninitialized_fill (ptr first, ptr last, const value_ty& val)
    2415             :   {
    2416             :     ptr curr = first;
    2417             :     PLUMED_GCH_TRY
    2418             :     {
    2419             :       for (; ! (curr == last); ++curr)
    2420             :         construct (curr, val);
    2421             :       return curr;
    2422             :     }
    2423             :     PLUMED_GCH_CATCH (...)
    2424             :     {
    2425             :       destroy_range (first, curr);
    2426             :       PLUMED_GCH_THROW;
    2427             :     }
    2428             :   }
    2429             : 
    2430             : private:
    2431             :   // If value_ty is an array, replicate C++20 behavior (I don't think that value_ty can
    2432             :   // actually be an array because of the Erasable requirement, but there shouldn't
    2433             :   // be any runtime cost for being defensive here).
    2434             :   template <typename V = value_ty,
    2435             :             typename std::enable_if<std::is_array<V>::value, bool>::type = true>
    2436             :   static PLUMED_GCH_CPP20_CONSTEXPR
    2437             :   void
    2438             :   destroy_at (value_ty *p) noexcept
    2439             :   {
    2440             :     for (auto& e : *p)
    2441             :       destroy_at (std::addressof (e));
    2442             :   }
    2443             : 
    2444             :   template <typename V = value_ty,
    2445             :             typename std::enable_if<! std::is_array<V>::value, bool>::type = false>
    2446             :   static PLUMED_GCH_CPP20_CONSTEXPR
    2447             :   void
    2448             :   destroy_at (value_ty *p) noexcept
    2449             :   {
    2450             :     p->~value_ty ();
    2451             :   }
    2452             : 
    2453             :   template <typename V = value_ty, typename ...Args>
    2454             :   static PLUMED_GCH_CPP20_CONSTEXPR
    2455             :   auto
    2456             :   construct_at (value_ty *p, Args&&... args)
    2457             :   noexcept (noexcept (::new (std::declval<void *> ()) V (std::declval<Args> ()...)))
    2458             :   -> decltype (::new (std::declval<void *> ()) V (std::declval<Args> ()...))
    2459             :   {
    2460             : #if defined (PLUMED_GCH_LIB_IS_CONSTANT_EVALUATED) && defined (PLUMED_GCH_LIB_CONSTEXPR_MEMORY)
    2461             :     if (std::is_constant_evaluated ())
    2462             :       return std::construct_at (p, std::forward<Args> (args)...);
    2463             : #endif
    2464             :     void *vp = const_cast<void *> (static_cast<const volatile void *> (p));
    2465             :     return ::new (vp) value_ty (std::forward<Args>(args)...);
    2466             :   }
    2467             : };
    2468             : 
    2469             : template <typename Pointer, typename SizeT>
    2470             : class small_vector_data_base
    2471             : {
    2472             : public:
    2473             :   using ptr     = Pointer;
    2474             :   using size_ty = SizeT;
    2475             : 
    2476             :   small_vector_data_base            (void)                              = default;
    2477             :   small_vector_data_base            (const small_vector_data_base&)     = default;
    2478             :   small_vector_data_base            (small_vector_data_base&&) noexcept = default;
    2479             :   small_vector_data_base& operator= (const small_vector_data_base&)     = default;
    2480             :   small_vector_data_base& operator= (small_vector_data_base&&) noexcept = default;
    2481             :   ~small_vector_data_base           (void)                              = default;
    2482             : 
    2483   150088598 :   constexpr ptr     data_ptr (void) const noexcept { return m_data_ptr; }
    2484     8031995 :   constexpr size_ty capacity (void) const noexcept { return m_capacity; }
    2485   183442755 :   constexpr size_ty size     (void) const noexcept { return m_size; }
    2486             : 
    2487     1639830 :   PLUMED_GCH_CPP20_CONSTEXPR void set_data_ptr (ptr     data_ptr) noexcept { m_data_ptr = data_ptr; }
    2488     1639830 :   PLUMED_GCH_CPP20_CONSTEXPR void set_capacity (size_ty capacity) noexcept { m_capacity = capacity; }
    2489     7559839 :   PLUMED_GCH_CPP20_CONSTEXPR void set_size     (size_ty size)     noexcept { m_size     = size;     }
    2490             : 
    2491             :   PLUMED_GCH_CPP20_CONSTEXPR
    2492             :   void
    2493             :   set (ptr data_ptr, size_ty capacity, size_ty size)
    2494             :   {
    2495        1313 :     m_data_ptr = data_ptr;
    2496        1313 :     m_capacity = capacity;
    2497        1313 :     m_size     = size;
    2498             :   }
    2499             : 
    2500             :   PLUMED_GCH_CPP20_CONSTEXPR
    2501             :   void
    2502             :   swap_data_ptr (small_vector_data_base& other) noexcept
    2503             :   {
    2504             :     using std::swap;
    2505             :     swap (m_data_ptr, other.m_data_ptr);
    2506             :   }
    2507             : 
    2508             :   PLUMED_GCH_CPP20_CONSTEXPR
    2509             :   void
    2510             :   swap_capacity (small_vector_data_base& other) noexcept
    2511             :   {
    2512             :     using std::swap;
    2513             :     swap (m_capacity, other.m_capacity);
    2514             :   }
    2515             : 
    2516             :   PLUMED_GCH_CPP20_CONSTEXPR
    2517             :   void
    2518             :   swap_size (small_vector_data_base& other) noexcept
    2519             :   {
    2520             :     using std::swap;
    2521             :     swap (m_size, other.m_size);
    2522             :   }
    2523             : 
    2524             :   PLUMED_GCH_CPP20_CONSTEXPR
    2525             :   void
    2526             :   swap (small_vector_data_base& other) noexcept
    2527             :   {
    2528             :     using std::swap;
    2529             :     swap (m_data_ptr, other.m_data_ptr);
    2530             :     swap (m_capacity, other.m_capacity);
    2531             :     swap (m_size,     other.m_size);
    2532             :   }
    2533             : 
    2534             : private:
    2535             :   ptr     m_data_ptr;
    2536             :   size_ty m_capacity;
    2537             :   size_ty m_size;
    2538             : };
    2539             : 
    2540             : template <typename Pointer, typename SizeT, typename T, unsigned InlineCapacity>
    2541             : class small_vector_data
    2542             : : public small_vector_data_base<Pointer, SizeT>
    2543             : {
    2544             : public:
    2545             :   using value_ty = T;
    2546             : 
    2547             :   small_vector_data            (void)                         = default;
    2548             :   small_vector_data            (const small_vector_data&)     = delete;
    2549             :   small_vector_data            (small_vector_data&&) noexcept = delete;
    2550             :   small_vector_data& operator= (const small_vector_data&)     = delete;
    2551             :   small_vector_data& operator= (small_vector_data&&) noexcept = delete;
    2552             :   ~small_vector_data           (void)                         = default;
    2553             : 
    2554             :   PLUMED_GCH_CPP14_CONSTEXPR
    2555             :   value_ty *
    2556             :   storage (void) noexcept
    2557             :   {
    2558             :     return m_storage.get_inline_ptr ();
    2559             :   }
    2560             : 
    2561             :   constexpr
    2562             :   const value_ty *
    2563             :   storage (void) const noexcept
    2564             :   {
    2565             :     return m_storage.get_inline_ptr ();
    2566             :   }
    2567             : 
    2568             : private:
    2569             :   inline_storage<value_ty, InlineCapacity> m_storage;
    2570             : };
    2571             : 
    2572             : template <typename Pointer, typename SizeT, typename T>
    2573             : class PLUMED_GCH_EMPTY_BASE small_vector_data<Pointer, SizeT, T, 0>
    2574             : : public  small_vector_data_base<Pointer, SizeT>,
    2575             : private inline_storage<T, 0>
    2576             : {
    2577             :   using base = inline_storage<T, 0>;
    2578             : 
    2579             : public:
    2580             :   using value_ty = T;
    2581             : 
    2582             :   small_vector_data            (void)                         = default;
    2583             :   small_vector_data            (const small_vector_data&)     = delete;
    2584             :   small_vector_data            (small_vector_data&&) noexcept = delete;
    2585             :   small_vector_data& operator= (const small_vector_data&)     = delete;
    2586             :   small_vector_data& operator= (small_vector_data&&) noexcept = delete;
    2587             :   ~small_vector_data           (void)                         = default;
    2588             : 
    2589             :   PLUMED_GCH_CPP14_CONSTEXPR
    2590             :   value_ty *
    2591             :   storage (void) noexcept
    2592             :   {
    2593             :     return base::get_inline_ptr ();
    2594             :   }
    2595             : 
    2596             :   constexpr
    2597             :   const value_ty *
    2598             :   storage (void) const noexcept
    2599             :   {
    2600             :     return base::get_inline_ptr ();
    2601             :   }
    2602             : };
    2603             : 
    2604             : template <typename Allocator, unsigned InlineCapacity>
    2605             : class small_vector_base
    2606             : : public allocator_interface<Allocator>
    2607             : {
    2608             : public:
    2609             :   using size_type       = typename allocator_interface<Allocator>::size_type;
    2610             :   using difference_type = typename allocator_interface<Allocator>::difference_type;
    2611             : 
    2612             :   template <typename SameAllocator, unsigned DifferentInlineCapacity>
    2613             :   friend class small_vector_base;
    2614             : 
    2615             : protected:
    2616             :   using alloc_interface = allocator_interface<Allocator>;
    2617             :   using alloc_traits    = typename alloc_interface::alloc_traits;
    2618             :   using alloc_ty        = Allocator;
    2619             : 
    2620             :   using value_ty        = typename alloc_interface::value_ty;
    2621             :   using ptr             = typename alloc_interface::ptr;
    2622             :   using cptr            = typename alloc_interface::cptr;
    2623             :   using size_ty         = typename alloc_interface::size_ty;
    2624             :   using diff_ty         = typename alloc_interface::diff_ty;
    2625             : 
    2626             :   static_assert (alloc_interface::template is_complete<value_ty>::value || InlineCapacity == 0,
    2627             :                  "`value_type` must be complete for instantiation of a non-zero number "
    2628             :                  "of inline elements.");
    2629             : 
    2630             :   template <typename T>
    2631             :   using is_complete = typename alloc_interface::template is_complete<T>;
    2632             : 
    2633             :   using alloc_interface::allocator_ref;
    2634             :   using alloc_interface::construct;
    2635             :   using alloc_interface::deallocate;
    2636             :   using alloc_interface::destroy;
    2637             :   using alloc_interface::destroy_range;
    2638             :   using alloc_interface::external_range_length;
    2639             :   using alloc_interface::get_max_size;
    2640             :   using alloc_interface::internal_range_length;
    2641             :   using alloc_interface::to_address;
    2642             :   using alloc_interface::unchecked_advance;
    2643             :   using alloc_interface::unchecked_next;
    2644             :   using alloc_interface::unchecked_prev;
    2645             :   using alloc_interface::uninitialized_copy;
    2646             :   using alloc_interface::uninitialized_fill;
    2647             :   using alloc_interface::uninitialized_value_construct;
    2648             : 
    2649             :   template <typename Integer>
    2650             :   PLUMED_GCH_NODISCARD
    2651             :   static PLUMED_GCH_CONSTEVAL
    2652             :   std::size_t
    2653             :   numeric_max (void) noexcept
    2654             :   {
    2655             :     return alloc_interface::template numeric_max<Integer> ();
    2656             :   }
    2657             : 
    2658             :   PLUMED_GCH_NODISCARD
    2659             :   static PLUMED_GCH_CONSTEVAL
    2660             :   size_ty
    2661             :   get_inline_capacity (void) noexcept
    2662             :   {
    2663             :     return static_cast<size_ty> (InlineCapacity);
    2664             :   }
    2665             : 
    2666             :   template <typename ...>
    2667             :   using void_t = void;
    2668             : 
    2669             :   template <bool B>
    2670             :   using bool_constant = std::integral_constant<bool, B>;
    2671             : 
    2672             :   template <typename Void, typename AI, typename V, typename ...Args>
    2673             :   struct is_emplace_constructible_impl
    2674             : : std::false_type
    2675             :   {
    2676             :     using nothrow = std::false_type;
    2677             :   };
    2678             : 
    2679             :   template <typename AI, typename V, typename ...Args>
    2680             :   struct is_emplace_constructible_impl<
    2681             :     void_t<typename std::enable_if<is_complete<V>::value>::type,
    2682             :            decltype (std::declval<AI&> ().construct (std::declval<V *> (),
    2683             :                      std::declval<Args> ()...))>,
    2684             :     AI, V, Args...>
    2685             : : std::true_type
    2686             :   {
    2687             :     using nothrow =
    2688             :     bool_constant<noexcept (std::declval<AI&> ().construct (std::declval<V *> (),
    2689             :                             std::declval<Args> ()...))>;
    2690             :                                                            };
    2691             : 
    2692             :   template <typename ...Args>
    2693             :   struct is_emplace_constructible
    2694             : : is_emplace_constructible_impl<void, alloc_interface, value_ty, Args...>
    2695             :   { };
    2696             : 
    2697             :   template <typename ...Args>
    2698             :   struct is_nothrow_emplace_constructible
    2699             : : is_emplace_constructible_impl<void, alloc_interface, value_ty, Args...>::nothrow
    2700             :   { };
    2701             : 
    2702             :   template <typename V = value_ty>
    2703             :   struct is_explicitly_move_insertable
    2704             : : is_emplace_constructible<V&&>
    2705             :   { };
    2706             : 
    2707             :   template <typename V = value_ty>
    2708             :   struct is_explicitly_nothrow_move_insertable
    2709             : : is_nothrow_emplace_constructible<V&&>
    2710             :   { };
    2711             : 
    2712             :   template <typename V = value_ty>
    2713             :   struct is_explicitly_copy_insertable
    2714             : : std::integral_constant<bool, is_emplace_constructible<V&>::value
    2715             :                            &&  is_emplace_constructible<const V&>::value>
    2716             :   { };
    2717             : 
    2718             :   template <typename V = value_ty>
    2719             :   struct is_explicitly_nothrow_copy_insertable
    2720             : : std::integral_constant<bool, is_nothrow_emplace_constructible<V&>::value
    2721             :                            &&  is_nothrow_emplace_constructible<const V&>::value>
    2722             :   { };
    2723             : 
    2724             :   template <typename AI, typename Enable = void>
    2725             :   struct is_eraseable
    2726             : : std::false_type
    2727             :   { };
    2728             : 
    2729             :   template <typename AI>
    2730             :   struct is_eraseable<AI,
    2731             :                       void_t<decltype (std::declval<AI&> ().destroy (std::declval<value_ty *> ()))>>
    2732             : : std::true_type
    2733             :   { };
    2734             : 
    2735             :   template <typename V>
    2736             :   struct relocate_with_move
    2737             : #ifdef PLUMED_GCH_NO_STRONG_EXCEPTION_GUARANTEES
    2738             : : std::true_type
    2739             : #else
    2740             : : bool_constant<std::is_nothrow_move_constructible<V>::value
    2741             :                   ||! is_explicitly_copy_insertable<V>::value>
    2742             : #endif
    2743             :   { };
    2744             : 
    2745             :   template <typename A>
    2746             :   struct allocations_are_movable
    2747             : : bool_constant<std::is_same<std::allocator<value_ty>, A>::value
    2748             :                   ||  std::allocator_traits<A>::propagate_on_container_move_assignment::value
    2749             : #ifdef PLUMED_GCH_LIB_IS_ALWAYS_EQUAL
    2750             :                   ||  std::allocator_traits<A>::is_always_equal::value
    2751             : #endif
    2752             :                   >
    2753             :   { };
    2754             : 
    2755             :   template <typename A>
    2756             :   struct allocations_are_swappable
    2757             : : bool_constant<std::is_same<std::allocator<value_ty>, A>::value
    2758             :                   ||  std::allocator_traits<A>::propagate_on_container_swap::value
    2759             : #ifdef PLUMED_GCH_LIB_IS_ALWAYS_EQUAL
    2760             :                   ||  std::allocator_traits<A>::is_always_equal::value
    2761             : #endif
    2762             :                   >
    2763             :   { };
    2764             : 
    2765             :   template <typename ...Args>
    2766             :   using is_memcpyable = typename alloc_interface::template is_memcpyable<Args...>;
    2767             : 
    2768             :   template <typename ...Args>
    2769             :   using is_memcpyable_iterator =
    2770             :   typename alloc_interface::template is_memcpyable_iterator<Args...>;
    2771             : 
    2772             :   PLUMED_GCH_NORETURN
    2773             :   static PLUMED_GCH_CPP20_CONSTEXPR
    2774             :   void
    2775             :   throw_overflow_error (void)
    2776             :   {
    2777             : #ifdef PLUMED_GCH_EXCEPTIONS
    2778             :     throw std::overflow_error ("The requested conversion would overflow.");
    2779             : #else
    2780             :     std::fprintf (stderr, "[gch::small_vector] The requested conversion would overflow.\n");
    2781             :     std::abort ();
    2782             : #endif
    2783             :   }
    2784             : 
    2785             :   PLUMED_GCH_NORETURN
    2786             :   static PLUMED_GCH_CPP20_CONSTEXPR
    2787             :   void
    2788             :   throw_index_error (void)
    2789             :   {
    2790             : #ifdef PLUMED_GCH_EXCEPTIONS
    2791             :     throw std::out_of_range ("The requested index was out of range.");
    2792             : #else
    2793             :     std::fprintf (stderr, "[gch::small_vector] The requested index was out of range.\n");
    2794             :     std::abort ();
    2795             : #endif
    2796             :   }
    2797             : 
    2798             :   PLUMED_GCH_NORETURN
    2799             :   static PLUMED_GCH_CPP20_CONSTEXPR
    2800             :   void
    2801             :   throw_increment_error (void)
    2802             :   {
    2803             : #ifdef PLUMED_GCH_EXCEPTIONS
    2804             :     throw std::domain_error ("The requested increment was outside of the allowed range.");
    2805             : #else
    2806             :     std::fprintf (
    2807             :       stderr,
    2808             :       "[gch::small_vector] The requested increment was outside of the allowed range.\n");
    2809             :     std::abort ();
    2810             : #endif
    2811             :   }
    2812             : 
    2813             :   PLUMED_GCH_NORETURN
    2814             :   static PLUMED_GCH_CPP20_CONSTEXPR
    2815             :   void
    2816           0 :   throw_allocation_size_error (void)
    2817             :   {
    2818             : #ifdef PLUMED_GCH_EXCEPTIONS
    2819           0 :     throw std::length_error ("The required allocation exceeds the maximum size.");
    2820             : #else
    2821             :     std::fprintf (
    2822             :       stderr,
    2823             :       "[gch::small_vector] The required allocation exceeds the maximum size.\n");
    2824             :     std::abort ();
    2825             : #endif
    2826             :   }
    2827             : 
    2828             :   PLUMED_GCH_NODISCARD PLUMED_GCH_CPP14_CONSTEXPR
    2829             :   ptr
    2830             :   ptr_cast (const small_vector_iterator<cptr, diff_ty>& it) noexcept
    2831             :   {
    2832             :     return unchecked_next (begin_ptr (), it.base () - begin_ptr ());
    2833             :   }
    2834             : 
    2835             : private:
    2836             :   class stack_temporary
    2837             :   {
    2838             :   public:
    2839             :     stack_temporary            (void)                       = delete;
    2840             :     stack_temporary            (const stack_temporary&)     = delete;
    2841             :     stack_temporary            (stack_temporary&&) noexcept = delete;
    2842             :     stack_temporary& operator= (const stack_temporary&)     = delete;
    2843             :     stack_temporary& operator= (stack_temporary&&) noexcept = delete;
    2844             : //      ~stack_temporary           (void)                       = impl;
    2845             : 
    2846             :     template <typename ...Args>
    2847             :     PLUMED_GCH_CPP20_CONSTEXPR explicit
    2848             :     stack_temporary (alloc_interface& alloc_iface, Args&&... args)
    2849             :       : m_interface (alloc_iface)
    2850             :     {
    2851             :       m_interface.construct (get_pointer (), std::forward<Args> (args)...);
    2852             :     }
    2853             : 
    2854             :     PLUMED_GCH_CPP20_CONSTEXPR
    2855             :     ~stack_temporary (void)
    2856             :     {
    2857             :       m_interface.destroy (get_pointer ());
    2858             :     }
    2859             : 
    2860             :     PLUMED_GCH_NODISCARD PLUMED_GCH_CPP20_CONSTEXPR
    2861             :     const value_ty&
    2862             :     get (void) const noexcept
    2863             :     {
    2864             :       return *get_pointer ();
    2865             :     }
    2866             : 
    2867             :     PLUMED_GCH_NODISCARD PLUMED_GCH_CPP20_CONSTEXPR
    2868             :     value_ty&&
    2869             :     release (void) noexcept
    2870             :     {
    2871             :       return std::move (*get_pointer ());
    2872             :     }
    2873             : 
    2874             :   private:
    2875             :     PLUMED_GCH_NODISCARD PLUMED_GCH_CPP20_CONSTEXPR
    2876             :     cptr
    2877             :     get_pointer (void) const noexcept
    2878             :     {
    2879             :       return static_cast<cptr> (static_cast<const void *> (std::addressof (m_data)));
    2880             :     }
    2881             : 
    2882             :     PLUMED_GCH_NODISCARD PLUMED_GCH_CPP20_CONSTEXPR
    2883             :     ptr
    2884             :     get_pointer (void) noexcept
    2885             :     {
    2886             :       return static_cast<ptr> (static_cast<void *> (std::addressof (m_data)));
    2887             :     }
    2888             : 
    2889             :     alloc_interface& m_interface;
    2890             :     typename std::aligned_storage<sizeof (value_ty), alignof (value_ty)>::type m_data;
    2891             :   };
    2892             : 
    2893             : #ifdef PLUMED_GCH_LIB_IS_CONSTANT_EVALUATED
    2894             : 
    2895             :   class heap_temporary
    2896             :   {
    2897             :   public:
    2898             :     heap_temporary            (void)                      = delete;
    2899             :     heap_temporary            (const heap_temporary&)     = delete;
    2900             :     heap_temporary            (heap_temporary&&) noexcept = delete;
    2901             :     heap_temporary& operator= (const heap_temporary&)     = delete;
    2902             :     heap_temporary& operator= (heap_temporary&&) noexcept = delete;
    2903             : //      ~heap_temporary           (void)                      = impl;
    2904             : 
    2905             :     template <typename ...Args>
    2906             :     PLUMED_GCH_CPP20_CONSTEXPR explicit
    2907             :     heap_temporary (alloc_interface& alloc_iface, Args&&... args)
    2908             :       : m_interface (alloc_iface),
    2909             :         m_data_ptr  (alloc_iface.allocate (sizeof (value_ty)))
    2910             :     {
    2911             :       PLUMED_GCH_TRY
    2912             :       {
    2913             :         m_interface.construct (m_data_ptr, std::forward<Args> (args)...);
    2914             :       }
    2915             :       PLUMED_GCH_CATCH (...)
    2916             :       {
    2917             :         m_interface.deallocate (m_data_ptr, sizeof (value_ty));
    2918             :         PLUMED_GCH_THROW;
    2919             :       }
    2920             :     }
    2921             : 
    2922             :     PLUMED_GCH_CPP20_CONSTEXPR
    2923             :     ~heap_temporary (void)
    2924             :     {
    2925             :       m_interface.destroy (m_data_ptr);
    2926             :       m_interface.deallocate (m_data_ptr, sizeof (value_ty));
    2927             :     }
    2928             : 
    2929             :     PLUMED_GCH_NODISCARD PLUMED_GCH_CPP20_CONSTEXPR
    2930             :     const value_ty&
    2931             :     get (void) const noexcept
    2932             :     {
    2933             :       return *m_data_ptr;
    2934             :     }
    2935             : 
    2936             :     PLUMED_GCH_NODISCARD PLUMED_GCH_CPP20_CONSTEXPR
    2937             :     value_ty&&
    2938             :     release (void) noexcept
    2939             :     {
    2940             :       return std::move (*m_data_ptr);
    2941             :     }
    2942             : 
    2943             :   private:
    2944             :     alloc_interface& m_interface;
    2945             :     ptr              m_data_ptr;
    2946             :   };
    2947             : 
    2948             : #endif
    2949             : 
    2950             :   PLUMED_GCH_CPP20_CONSTEXPR
    2951             :   void
    2952     1617101 :   wipe (void)
    2953             :   {
    2954     1617101 :     destroy_range (begin_ptr (), end_ptr ());
    2955     1617101 :     if (has_allocation ())
    2956             :       deallocate (data_ptr (), get_capacity ());
    2957     1617101 :   }
    2958             : 
    2959             :   PLUMED_GCH_CPP20_CONSTEXPR
    2960             :   void
    2961             :   set_data_ptr (ptr data_ptr) noexcept
    2962             :   {
    2963             :     m_data.set_data_ptr (data_ptr);
    2964             :   }
    2965             : 
    2966             :   PLUMED_GCH_CPP20_CONSTEXPR
    2967             :   void
    2968             :   set_capacity (size_ty capacity) noexcept
    2969             :   {
    2970             :     m_data.set_capacity (static_cast<size_type> (capacity));
    2971        2344 :   }
    2972             : 
    2973             :   PLUMED_GCH_CPP20_CONSTEXPR
    2974             :   void
    2975             :   set_size (size_ty size) noexcept
    2976             :   {
    2977             :     m_data.set_size (static_cast<size_type> (size));
    2978     4208848 :   }
    2979             : 
    2980             :   PLUMED_GCH_CPP20_CONSTEXPR
    2981             :   void
    2982             :   set_data (ptr data_ptr, size_ty capacity, size_ty size) noexcept
    2983             :   {
    2984             :     m_data.set (data_ptr, static_cast<size_type> (capacity), static_cast<size_type> (size));
    2985             :   }
    2986             : 
    2987             :   PLUMED_GCH_CPP20_CONSTEXPR
    2988             :   void
    2989             :   swap_data_ptr (small_vector_base& other) noexcept
    2990             :   {
    2991             :     m_data.swap_data_ptr (other.m_data);
    2992             :   }
    2993             : 
    2994             :   PLUMED_GCH_CPP20_CONSTEXPR
    2995             :   void
    2996             :   swap_capacity (small_vector_base& other) noexcept
    2997             :   {
    2998             :     m_data.swap_capacity (other.m_data);
    2999             :   }
    3000             : 
    3001             :   PLUMED_GCH_CPP20_CONSTEXPR
    3002             :   void
    3003             :   swap_size (small_vector_base& other) noexcept
    3004             :   {
    3005             :     m_data.swap_size (other.m_data);
    3006             :   }
    3007             : 
    3008             :   PLUMED_GCH_CPP20_CONSTEXPR
    3009             :   void
    3010             :   swap_allocation (small_vector_base& other) noexcept
    3011             :   {
    3012             :     m_data.swap (other.m_data);
    3013             :   }
    3014             : 
    3015             :   PLUMED_GCH_CPP20_CONSTEXPR
    3016             :   void
    3017             :   reset_data (ptr data_ptr, size_ty capacity, size_ty size)
    3018             :   {
    3019        1313 :     wipe ();
    3020             :     m_data.set (data_ptr, static_cast<size_type> (capacity), static_cast<size_type> (size));
    3021           0 :   }
    3022             : 
    3023             :   PLUMED_GCH_CPP20_CONSTEXPR
    3024             :   void
    3025             :   increase_size (size_ty n) noexcept
    3026             :   {
    3027     2149600 :     m_data.set_size (get_size () + n);
    3028             :   }
    3029             : 
    3030             :   PLUMED_GCH_CPP20_CONSTEXPR
    3031             :   void
    3032             :   decrease_size (size_ty n) noexcept
    3033             :   {
    3034      137267 :     m_data.set_size (get_size () - n);
    3035             :   }
    3036             : 
    3037             :   PLUMED_GCH_CPP20_CONSTEXPR
    3038             :   ptr
    3039             :   unchecked_allocate (size_ty n)
    3040             :   {
    3041             :     assert (InlineCapacity < n && "Allocated capacity should be greater than InlineCapacity.");
    3042             :     return alloc_interface::allocate (n);
    3043             :   }
    3044             : 
    3045             :   PLUMED_GCH_CPP20_CONSTEXPR
    3046             :   ptr
    3047             :   unchecked_allocate (size_ty n, cptr hint)
    3048             :   {
    3049             :     assert (InlineCapacity < n && "Allocated capacity should be greater than InlineCapacity.");
    3050             :     return alloc_interface::allocate_with_hint (n, hint);
    3051             :   }
    3052             : 
    3053             :   PLUMED_GCH_CPP20_CONSTEXPR
    3054             :   ptr
    3055           0 :   checked_allocate (size_ty n)
    3056             :   {
    3057           0 :     if (get_max_size () < n)
    3058           0 :       throw_allocation_size_error ();
    3059           0 :     return unchecked_allocate (n);
    3060             :   }
    3061             : 
    3062             : protected:
    3063             :   PLUMED_GCH_NODISCARD PLUMED_GCH_CPP14_CONSTEXPR
    3064             :   size_ty
    3065             :   unchecked_calculate_new_capacity (const size_ty minimum_required_capacity) const noexcept
    3066             :   {
    3067             :     const size_ty current_capacity = get_capacity ();
    3068             : 
    3069             :     assert (current_capacity < minimum_required_capacity);
    3070             : 
    3071        2516 :     if (get_max_size () - current_capacity <= current_capacity)
    3072             :       return get_max_size ();
    3073             : 
    3074             :     // Note: This growth factor might be theoretically superior, but in testing it falls flat:
    3075             :     // size_ty new_capacity = current_capacity + (current_capacity / 2);
    3076             : 
    3077        3657 :     const size_ty new_capacity = 2 * current_capacity;
    3078             :     if (new_capacity < minimum_required_capacity)
    3079             :       return minimum_required_capacity;
    3080             :     return new_capacity;
    3081             :   }
    3082             : 
    3083             :   PLUMED_GCH_NODISCARD PLUMED_GCH_CPP14_CONSTEXPR
    3084             :   size_ty
    3085        2344 :   checked_calculate_new_capacity (const size_ty minimum_required_capacity) const
    3086             :   {
    3087        2344 :     if (get_max_size () < minimum_required_capacity)
    3088           0 :       throw_allocation_size_error ();
    3089        2344 :     return unchecked_calculate_new_capacity (minimum_required_capacity);
    3090             :   }
    3091             : 
    3092             :   template <unsigned I>
    3093             :   PLUMED_GCH_CPP20_CONSTEXPR
    3094             :   small_vector_base&
    3095     4208848 :   copy_assign_default (const small_vector_base<Allocator, I>& other)
    3096             :   {
    3097     4208848 :     if (get_capacity () < other.get_size ())
    3098             :     {
    3099             :       // Reallocate.
    3100             :       size_ty new_capacity = unchecked_calculate_new_capacity (other.get_size ());
    3101           0 :       ptr     new_data_ptr = unchecked_allocate (new_capacity, other.allocation_end_ptr ());
    3102             : 
    3103             :       PLUMED_GCH_TRY
    3104             :       {
    3105           0 :         uninitialized_copy (other.begin_ptr (), other.end_ptr (), new_data_ptr);
    3106             :       }
    3107             :       PLUMED_GCH_CATCH (...)
    3108             :       {
    3109             :         deallocate (new_data_ptr, new_capacity);
    3110             :         PLUMED_GCH_THROW;
    3111             :       }
    3112             : 
    3113             :       reset_data (new_data_ptr, new_capacity, other.get_size ());
    3114             :     }
    3115             :     else
    3116             :     {
    3117     4208848 :       if (get_size () < other.get_size ())
    3118             :       {
    3119             :         // No reallocation, partially in uninitialized space.
    3120       20368 :         std::copy_n (other.begin_ptr (), get_size (), begin_ptr ());
    3121       40736 :         uninitialized_copy (
    3122             :           unchecked_next (other.begin_ptr (), get_size ()),
    3123             :           other.end_ptr (),
    3124             :           end_ptr ());
    3125             :       }
    3126             :       else
    3127             :       {
    3128     4188480 :         destroy_range (copy_range (other.begin_ptr (), other.end_ptr (), begin_ptr ()),
    3129             :                        end_ptr ());
    3130             :       }
    3131             : 
    3132             :       // data_ptr and capacity do not change in this case.
    3133             :       set_size (other.get_size ());
    3134             :     }
    3135             : 
    3136             :     alloc_interface::operator= (other);
    3137     4208848 :     return *this;
    3138             :   }
    3139             : 
    3140             :   template <unsigned I, typename AT = alloc_traits,
    3141             :             typename std::enable_if<AT::propagate_on_container_copy_assignment::value
    3142             : #ifdef PLUMED_GCH_LIB_IS_ALWAYS_EQUAL
    3143             :                                     &&! AT::is_always_equal::value
    3144             : #endif
    3145             :                                     >::type * = nullptr>
    3146             :   PLUMED_GCH_CPP20_CONSTEXPR
    3147             :   small_vector_base&
    3148             :   copy_assign (const small_vector_base<Allocator, I>& other)
    3149             :   {
    3150             :     if (other.allocator_ref () == allocator_ref ())
    3151             :       return copy_assign_default (other);
    3152             : 
    3153             :     if (InlineCapacity < other.get_size ())
    3154             :     {
    3155             :       alloc_interface new_alloc (other);
    3156             : 
    3157             :       const size_ty new_capacity = other.get_size ();
    3158             :       const ptr new_data_ptr = new_alloc.allocate_with_hint (
    3159             :                                  new_capacity,
    3160             :                                  other.allocation_end_ptr ());
    3161             : 
    3162             :       PLUMED_GCH_TRY
    3163             :       {
    3164             :         uninitialized_copy (other.begin_ptr (), other.end_ptr (), new_data_ptr);
    3165             :       }
    3166             :       PLUMED_GCH_CATCH (...)
    3167             :       {
    3168             :         new_alloc.deallocate (new_data_ptr, new_capacity);
    3169             :         PLUMED_GCH_THROW;
    3170             :       }
    3171             : 
    3172             :       reset_data (new_data_ptr, new_capacity, other.get_size ());
    3173             :       alloc_interface::operator= (new_alloc);
    3174             :     }
    3175             :     else
    3176             :     {
    3177             :       if (has_allocation ())
    3178             :       {
    3179             : #ifdef PLUMED_GCH_LIB_IS_CONSTANT_EVALUATED
    3180             :         ptr new_data_ptr;
    3181             :         if (std::is_constant_evaluated ())
    3182             :         {
    3183             :           alloc_interface new_alloc (other);
    3184             :           new_data_ptr = new_alloc.allocate (InlineCapacity);
    3185             :         }
    3186             :         else
    3187             :           new_data_ptr = storage_ptr ();
    3188             : #else
    3189             :         const ptr new_data_ptr = storage_ptr ();
    3190             : #endif
    3191             : 
    3192             :         uninitialized_copy (other.begin_ptr (), other.end_ptr (), new_data_ptr);
    3193             :         destroy_range (begin_ptr (), end_ptr ());
    3194             :         deallocate (data_ptr (), get_capacity ());
    3195             :         set_data_ptr (new_data_ptr);
    3196             :         set_capacity (InlineCapacity);
    3197             :       }
    3198             :       else if (get_size () < other.get_size ())
    3199             :       {
    3200             :         std::copy_n (other.begin_ptr (), get_size (), begin_ptr ());
    3201             :         uninitialized_copy (
    3202             :           unchecked_next (other.begin_ptr (), get_size ()),
    3203             :           other.end_ptr (),
    3204             :           end_ptr ());
    3205             :       }
    3206             :       else
    3207             :       {
    3208             :         destroy_range (copy_range (other.begin_ptr (), other.end_ptr (), begin_ptr ()),
    3209             :                        end_ptr ());
    3210             :       }
    3211             :       set_size (other.get_size ());
    3212             :       alloc_interface::operator= (other);
    3213             :     }
    3214             : 
    3215             :     return *this;
    3216             :   }
    3217             : 
    3218             :   template <unsigned I, typename AT = alloc_traits,
    3219             :             typename std::enable_if<! AT::propagate_on_container_copy_assignment::value
    3220             : #ifdef PLUMED_GCH_LIB_IS_ALWAYS_EQUAL
    3221             :                                     ||  AT::is_always_equal::value
    3222             : #endif
    3223             :                                     >::type * = nullptr>
    3224             :   PLUMED_GCH_CPP20_CONSTEXPR
    3225             :   small_vector_base&
    3226             :   copy_assign (const small_vector_base<Allocator, I>& other)
    3227             :   {
    3228             :     return copy_assign_default (other);
    3229             :   }
    3230             : 
    3231             :   template <unsigned I>
    3232             :   PLUMED_GCH_CPP20_CONSTEXPR
    3233             :   void
    3234             :   move_allocation_pointer (small_vector_base<alloc_ty, I>&& other) noexcept
    3235             :   {
    3236             :     reset_data (other.data_ptr (), other.get_capacity (), other.get_size ());
    3237             :     other.set_default ();
    3238             :   }
    3239             : 
    3240             :   template <unsigned N = InlineCapacity, typename std::enable_if<N == 0>::type * = nullptr>
    3241             :   PLUMED_GCH_CPP20_CONSTEXPR
    3242             :   small_vector_base&
    3243             :   move_assign_default (small_vector_base&& other) noexcept
    3244             :   {
    3245             :     move_allocation_pointer (std::move (other));
    3246             :     alloc_interface::operator= (std::move (other));
    3247             :     return *this;
    3248             :   }
    3249             : 
    3250             :   template <unsigned LessEqualI,
    3251             :             typename std::enable_if<(LessEqualI <= InlineCapacity)>::type * = nullptr>
    3252             :             PLUMED_GCH_CPP20_CONSTEXPR
    3253             :             small_vector_base&
    3254             :             move_assign_default (small_vector_base<Allocator, LessEqualI>&& other)
    3255             :             noexcept (std::is_nothrow_move_assignable<value_ty>::value
    3256             :                       &&  std::is_nothrow_move_constructible<value_ty>::value)
    3257             :   {
    3258             :     // We only move the allocation pointer over if it has strictly greater capacity than
    3259             :     // the inline capacity of `*this` because allocations can never have a smaller capacity
    3260             :     // than the inline capacity.
    3261             :     if (InlineCapacity < other.get_capacity ())
    3262             :           move_allocation_pointer (std::move (other));
    3263             :     else
    3264             :     {
    3265             :       // We are guaranteed to have sufficient capacity to store the elements.
    3266             :       if (InlineCapacity < get_capacity ())
    3267             :       {
    3268             : #ifdef PLUMED_GCH_LIB_IS_CONSTANT_EVALUATED
    3269             :         ptr new_data_ptr;
    3270             :         if (std::is_constant_evaluated ())
    3271             :           new_data_ptr = other.allocate (InlineCapacity);
    3272             :         else
    3273             :           new_data_ptr = storage_ptr ();
    3274             : #else
    3275             :         const ptr new_data_ptr = storage_ptr ();
    3276             : #endif
    3277             : 
    3278             :         uninitialized_move (other.begin_ptr (), other.end_ptr (), new_data_ptr);
    3279             :         destroy_range (begin_ptr (), end_ptr ());
    3280             :         deallocate (data_ptr (), get_capacity ());
    3281             :         set_data_ptr (new_data_ptr);
    3282             :         set_capacity (InlineCapacity);
    3283             :       }
    3284             :       else if (get_size () < other.get_size ())
    3285             :       {
    3286             :         // There are more elements in `other`.
    3287             :         // Overwrite the existing range and uninitialized move the rest.
    3288             :         ptr other_pivot = unchecked_next (other.begin_ptr (), get_size ());
    3289             :         std::move (other.begin_ptr (), other_pivot, begin_ptr ());
    3290             :         uninitialized_move (other_pivot, other.end_ptr (), end_ptr ());
    3291             :       }
    3292             :       else
    3293             :       {
    3294             :         // There are the same number or fewer elements in `other`.
    3295             :         // Overwrite part of the existing range and destroy the rest.
    3296             :         ptr new_end = std::move (other.begin_ptr (), other.end_ptr (), begin_ptr ());
    3297             :         destroy_range (new_end, end_ptr ());
    3298             :       }
    3299             : 
    3300             :       set_size (other.get_size ());
    3301             : 
    3302             :       // Note: We do not need to deallocate any allocations in `other` because the value of
    3303             :       //       an object meeting the Allocator named requirements does not change value after
    3304             :       //       a move.
    3305             :     }
    3306             : 
    3307             :     alloc_interface::operator= (std::move (other));
    3308             :     return *this;
    3309             :   }
    3310             : 
    3311             :   template <unsigned GreaterI,
    3312             :             typename std::enable_if<(InlineCapacity < GreaterI)>::type * = nullptr>
    3313             :             PLUMED_GCH_CPP20_CONSTEXPR
    3314             :             small_vector_base&
    3315             :             move_assign_default (small_vector_base<Allocator, GreaterI>&& other)
    3316             :   {
    3317             :     if (other.has_allocation ())
    3318             :       move_allocation_pointer (std::move (other));
    3319             :     else if (get_capacity () < other.get_size ()
    3320             :              ||  (has_allocation () && ! (other.allocator_ref () == allocator_ref ())))
    3321             :     {
    3322             :       // Reallocate.
    3323             : 
    3324             :       // The compiler should be able to optimize this.
    3325             :       size_ty new_capacity =
    3326             :         get_capacity () < other.get_size ()
    3327             :         ? unchecked_calculate_new_capacity (other.get_size ())
    3328             :         : get_capacity ();
    3329             : 
    3330             :       ptr new_data_ptr = other.allocate_with_hint (new_capacity, other.allocation_end_ptr ());
    3331             : 
    3332             :       PLUMED_GCH_TRY
    3333             :       {
    3334             :         uninitialized_move (other.begin_ptr (), other.end_ptr (), new_data_ptr);
    3335             :       }
    3336             :       PLUMED_GCH_CATCH (...)
    3337             :       {
    3338             :         other.deallocate (new_data_ptr, new_capacity);
    3339             :         PLUMED_GCH_THROW;
    3340             :       }
    3341             : 
    3342             :       reset_data (new_data_ptr, new_capacity, other.get_size ());
    3343             :     }
    3344             :     else
    3345             :     {
    3346             :       if (get_size () < other.get_size ())
    3347             :       {
    3348             :         // There are more elements in `other`.
    3349             :         // Overwrite the existing range and uninitialized move the rest.
    3350             :         ptr other_pivot = unchecked_next (other.begin_ptr (), get_size ());
    3351             :         std::move (other.begin_ptr (), other_pivot, begin_ptr ());
    3352             :         uninitialized_move (other_pivot, other.end_ptr (), end_ptr ());
    3353             :       }
    3354             :       else
    3355             :       {
    3356             :         // fewer elements in other
    3357             :         // overwrite part of the existing range and destroy the rest
    3358             :         ptr new_end = std::move (other.begin_ptr (), other.end_ptr (), begin_ptr ());
    3359             :         destroy_range (new_end, end_ptr ());
    3360             :       }
    3361             : 
    3362             :       // `data_ptr` and `capacity` do not change in this case.
    3363             :       set_size (other.get_size ());
    3364             :     }
    3365             : 
    3366             :     alloc_interface::operator= (std::move (other));
    3367             :     return *this;
    3368             :   }
    3369             : 
    3370             :   template <unsigned I>
    3371             :   PLUMED_GCH_CPP20_CONSTEXPR
    3372             :   small_vector_base&
    3373             :   move_assign_unequal_no_propagate (small_vector_base<Allocator, I>&& other)
    3374             :   {
    3375             :     if (get_capacity () < other.get_size ())
    3376             :     {
    3377             :       // Reallocate.
    3378             :       size_ty new_capacity = unchecked_calculate_new_capacity (other.get_size ());
    3379             :       ptr     new_data_ptr = unchecked_allocate (new_capacity, other.allocation_end_ptr ());
    3380             : 
    3381             :       PLUMED_GCH_TRY
    3382             :       {
    3383             :         uninitialized_move (other.begin_ptr (), other.end_ptr (), new_data_ptr);
    3384             :       }
    3385             :       PLUMED_GCH_CATCH (...)
    3386             :       {
    3387             :         deallocate (new_data_ptr, new_capacity);
    3388             :         PLUMED_GCH_THROW;
    3389             :       }
    3390             : 
    3391             :       reset_data (new_data_ptr, new_capacity, other.get_size ());
    3392             :     }
    3393             :     else
    3394             :     {
    3395             :       if (get_size () < other.get_size ())
    3396             :       {
    3397             :         // There are more elements in `other`.
    3398             :         // Overwrite the existing range and uninitialized move the rest.
    3399             :         ptr other_pivot = unchecked_next (other.begin_ptr (), get_size ());
    3400             :         std::move (other.begin_ptr (), other_pivot, begin_ptr ());
    3401             :         uninitialized_move (other_pivot, other.end_ptr (), end_ptr ());
    3402             :       }
    3403             :       else
    3404             :       {
    3405             :         // There are fewer elements in `other`.
    3406             :         // Overwrite part of the existing range and destroy the rest.
    3407             :         destroy_range (
    3408             :           std::move (other.begin_ptr (), other.end_ptr (), begin_ptr ()),
    3409             :           end_ptr ());
    3410             :       }
    3411             : 
    3412             :       // data_ptr and capacity do not change in this case
    3413             :       set_size (other.get_size ());
    3414             :     }
    3415             : 
    3416             :     alloc_interface::operator= (std::move (other));
    3417             :     return *this;
    3418             :   }
    3419             : 
    3420             :   template <unsigned I, typename A = alloc_ty,
    3421             :             typename std::enable_if<allocations_are_movable<A>::value>::type * = nullptr>
    3422             :   PLUMED_GCH_CPP20_CONSTEXPR
    3423             :   small_vector_base&
    3424             :   move_assign (small_vector_base<Allocator, I>&& other)
    3425             :   noexcept (noexcept (
    3426             :               std::declval<small_vector_base&> ().move_assign_default (std::move (other))))
    3427             :   {
    3428             :     return move_assign_default (std::move (other));
    3429             :   }
    3430             : 
    3431             :   template <unsigned I, typename A = alloc_ty,
    3432             :             typename std::enable_if<! allocations_are_movable<A>::value>::type * = nullptr>
    3433             :   PLUMED_GCH_CPP20_CONSTEXPR
    3434             :   small_vector_base&
    3435             :   move_assign (small_vector_base<Allocator, I>&& other)
    3436             :   {
    3437             :     if (other.allocator_ref () == allocator_ref ())
    3438             :       return move_assign_default (std::move (other));
    3439             :     return move_assign_unequal_no_propagate (std::move (other));
    3440             :   }
    3441             : 
    3442             :   template <unsigned I = InlineCapacity,
    3443             :             typename std::enable_if<I == 0>::type * = nullptr>
    3444             :   PLUMED_GCH_CPP20_CONSTEXPR
    3445             :   void
    3446             :   move_initialize (small_vector_base&& other) noexcept
    3447             :   {
    3448             :     set_data (other.data_ptr (), other.get_capacity (), other.get_size ());
    3449             :     other.set_default ();
    3450             :   }
    3451             : 
    3452             :   template <unsigned LessEqualI,
    3453             :             typename std::enable_if<(LessEqualI <= InlineCapacity)>::type * = nullptr>
    3454             :             PLUMED_GCH_CPP20_CONSTEXPR
    3455             :             void
    3456             :             move_initialize (small_vector_base<Allocator, LessEqualI>&& other)
    3457             :             noexcept (std::is_nothrow_move_constructible<value_ty>::value)
    3458             :   {
    3459             :     if (InlineCapacity < other.get_capacity ())
    3460             :     {
    3461             :       set_data (other.data_ptr (), other.get_capacity (), other.get_size ());
    3462             :       other.set_default ();
    3463             :     }
    3464             :     else
    3465             :     {
    3466             :       set_to_inline_storage ();
    3467             :       uninitialized_move (other.begin_ptr (), other.end_ptr (), data_ptr ());
    3468             :       set_size (other.get_size ());
    3469             :     }
    3470             :   }
    3471             : 
    3472             :   template <unsigned GreaterI,
    3473             :             typename std::enable_if<(InlineCapacity < GreaterI)>::type * = nullptr>
    3474             :             PLUMED_GCH_CPP20_CONSTEXPR
    3475             :             void
    3476             :             move_initialize (small_vector_base<Allocator, GreaterI>&& other)
    3477             :   {
    3478             :     if (other.has_allocation ())
    3479             :     {
    3480             :       set_data (other.data_ptr (), other.get_capacity (), other.get_size ());
    3481             :       other.set_default ();
    3482             :     }
    3483             :     else
    3484             :     {
    3485             :       if (InlineCapacity < other.get_size ())
    3486             :       {
    3487             :         // We may throw in this case.
    3488             :         set_data_ptr (unchecked_allocate (other.get_size (), other.allocation_end_ptr ()));
    3489             :         set_capacity (other.get_size ());
    3490             : 
    3491             :         PLUMED_GCH_TRY
    3492             :         {
    3493             :           uninitialized_move (other.begin_ptr (), other.end_ptr (), data_ptr ());
    3494             :         }
    3495             :         PLUMED_GCH_CATCH (...)
    3496             :         {
    3497             :           deallocate (data_ptr (), get_capacity ());
    3498             :           PLUMED_GCH_THROW;
    3499             :         }
    3500             :       }
    3501             :       else
    3502             :       {
    3503             :         set_to_inline_storage ();
    3504             :         uninitialized_move (other.begin_ptr (), other.end_ptr (), data_ptr ());
    3505             :       }
    3506             : 
    3507             :       set_size (other.get_size ());
    3508             :     }
    3509             :   }
    3510             : 
    3511             : public:
    3512             : //    small_vector_base            (void)                         = impl;
    3513             :   small_vector_base            (const small_vector_base&)     = delete;
    3514             :   small_vector_base            (small_vector_base&&) noexcept = delete;
    3515             :   small_vector_base& operator= (const small_vector_base&)     = delete;
    3516             :   small_vector_base& operator= (small_vector_base&&) noexcept = delete;
    3517             : //    ~small_vector_base           (void)                         = impl;
    3518             : 
    3519             :   PLUMED_GCH_CPP20_CONSTEXPR
    3520     1609758 :   small_vector_base (void) noexcept
    3521             :   {
    3522             :     set_default ();
    3523             :   }
    3524             : 
    3525             :   static constexpr struct bypass_tag { } bypass { };
    3526             : 
    3527             :   template <unsigned I, typename ...MaybeAlloc>
    3528             :   PLUMED_GCH_CPP20_CONSTEXPR
    3529             :   small_vector_base (bypass_tag,
    3530             :                      const small_vector_base<Allocator, I>& other,
    3531             :                      const MaybeAlloc&... alloc)
    3532             :     : alloc_interface (other, alloc...)
    3533             :   {
    3534             :     if (InlineCapacity < other.get_size ())
    3535             :     {
    3536             :       set_data_ptr (unchecked_allocate (other.get_size (), other.allocation_end_ptr ()));
    3537             :       set_capacity (other.get_size ());
    3538             : 
    3539             :       PLUMED_GCH_TRY
    3540             :       {
    3541             :         uninitialized_copy (other.begin_ptr (), other.end_ptr (), data_ptr ());
    3542             :       }
    3543             :       PLUMED_GCH_CATCH (...)
    3544             :       {
    3545             :         deallocate (data_ptr (), get_capacity ());
    3546             :         PLUMED_GCH_THROW;
    3547             :       }
    3548             :     }
    3549             :     else
    3550             :     {
    3551             :       set_to_inline_storage ();
    3552             :       uninitialized_copy (other.begin_ptr (), other.end_ptr (), data_ptr ());
    3553             :     }
    3554             : 
    3555             :     set_size (other.get_size ());
    3556             :   }
    3557             : 
    3558             :   template <unsigned I>
    3559             :   PLUMED_GCH_CPP20_CONSTEXPR
    3560             :   small_vector_base (bypass_tag, small_vector_base<Allocator, I>&& other)
    3561             :   noexcept (std::is_nothrow_move_constructible<value_ty>::value
    3562             :             ||  (I == 0 && I == InlineCapacity))
    3563             :     : alloc_interface (std::move (other))
    3564             :   {
    3565             :     move_initialize (std::move (other));
    3566             :   }
    3567             : 
    3568             :   template <unsigned I, typename A = alloc_ty,
    3569             :             typename std::enable_if<std::is_same<std::allocator<value_ty>, A>::value
    3570             : #ifdef PLUMED_GCH_LIB_IS_ALWAYS_EQUAL
    3571             :                                     ||  std::allocator_traits<A>::is_always_equal::value
    3572             : #endif
    3573             :                                     >::type * = nullptr>
    3574             :   PLUMED_GCH_CPP20_CONSTEXPR
    3575             :   small_vector_base (bypass_tag, small_vector_base<Allocator, I>&& other, const alloc_ty&)
    3576             :   noexcept (noexcept (small_vector_base (bypass, std::move (other))))
    3577             :     : small_vector_base (bypass, std::move (other))
    3578             :   { }
    3579             : 
    3580             :   template <unsigned I, typename A = alloc_ty,
    3581             :             typename std::enable_if<! (std::is_same<std::allocator<value_ty>, A>::value
    3582             : #ifdef PLUMED_GCH_LIB_IS_ALWAYS_EQUAL
    3583             :                                        ||  std::allocator_traits<A>::is_always_equal::value
    3584             : #endif
    3585             :                                                                 )>::type * = nullptr>
    3586             :   PLUMED_GCH_CPP20_CONSTEXPR
    3587             :   small_vector_base (bypass_tag, small_vector_base<Allocator, I>&& other, const alloc_ty& alloc)
    3588             :     : alloc_interface (alloc)
    3589             :   {
    3590             :     if (other.allocator_ref () == alloc)
    3591             :     {
    3592             :       move_initialize (std::move (other));
    3593             :       return;
    3594             :     }
    3595             : 
    3596             :     if (InlineCapacity < other.get_size ())
    3597             :     {
    3598             :       // We may throw in this case.
    3599             :       set_data_ptr (unchecked_allocate (other.get_size (), other.allocation_end_ptr ()));
    3600             :       set_capacity (other.get_size ());
    3601             : 
    3602             :       PLUMED_GCH_TRY
    3603             :       {
    3604             :         uninitialized_move (other.begin_ptr (), other.end_ptr (), data_ptr ());
    3605             :       }
    3606             :       PLUMED_GCH_CATCH (...)
    3607             :       {
    3608             :         deallocate (data_ptr (), get_capacity ());
    3609             :         PLUMED_GCH_THROW;
    3610             :       }
    3611             :     }
    3612             :     else
    3613             :     {
    3614             :       set_to_inline_storage ();
    3615             :       uninitialized_move (other.begin_ptr (), other.end_ptr (), data_ptr ());
    3616             :     }
    3617             : 
    3618             :     set_size (other.get_size ());
    3619             :   }
    3620             : 
    3621             :   PLUMED_GCH_CPP20_CONSTEXPR explicit
    3622             :   small_vector_base (const alloc_ty& alloc) noexcept
    3623             :     : alloc_interface (alloc)
    3624             :   {
    3625             :     set_default ();
    3626             :   }
    3627             : 
    3628             :   PLUMED_GCH_CPP20_CONSTEXPR
    3629        3738 :   small_vector_base (size_ty count, const alloc_ty& alloc)
    3630             :     : alloc_interface (alloc)
    3631             :   {
    3632        3738 :     if (InlineCapacity < count)
    3633             :     {
    3634           0 :       set_data_ptr (checked_allocate (count));
    3635             :       set_capacity (count);
    3636             :     }
    3637             :     else
    3638             :       set_to_inline_storage ();
    3639             : 
    3640             :     PLUMED_GCH_TRY
    3641             :     {
    3642        3738 :       uninitialized_value_construct (begin_ptr (), unchecked_next (begin_ptr (), count));
    3643             :     }
    3644             :     PLUMED_GCH_CATCH (...)
    3645             :     {
    3646             :       if (has_allocation ())
    3647             :         deallocate (data_ptr (), get_capacity ());
    3648             :       PLUMED_GCH_THROW;
    3649             :     }
    3650             :     set_size (count);
    3651        3738 :   }
    3652             : 
    3653             :   PLUMED_GCH_CPP20_CONSTEXPR
    3654             :   small_vector_base (size_ty count, const value_ty& val, const alloc_ty& alloc)
    3655             :     : alloc_interface (alloc)
    3656             :   {
    3657             :     if (InlineCapacity < count)
    3658             :     {
    3659             :       set_data_ptr (checked_allocate (count));
    3660             :       set_capacity (count);
    3661             :     }
    3662             :     else
    3663             :       set_to_inline_storage ();
    3664             : 
    3665             :     PLUMED_GCH_TRY
    3666             :     {
    3667             :       uninitialized_fill (begin_ptr (), unchecked_next (begin_ptr (), count), val);
    3668             :     }
    3669             :     PLUMED_GCH_CATCH (...)
    3670             :     {
    3671             :       if (has_allocation ())
    3672             :         deallocate (data_ptr (), get_capacity ());
    3673             :       PLUMED_GCH_THROW;
    3674             :     }
    3675             :     set_size (count);
    3676             :   }
    3677             : 
    3678             :   template <typename Generator>
    3679             :   PLUMED_GCH_CPP20_CONSTEXPR
    3680             :   small_vector_base (size_ty count, Generator& g, const alloc_ty& alloc)
    3681             :     : alloc_interface (alloc)
    3682             :   {
    3683             :     if (InlineCapacity < count)
    3684             :     {
    3685             :       set_data_ptr (checked_allocate (count));
    3686             :       set_capacity (count);
    3687             :     }
    3688             :     else
    3689             :       set_to_inline_storage ();
    3690             : 
    3691             :     ptr curr = begin_ptr ();
    3692             :     const ptr new_end = unchecked_next (begin_ptr (), count);
    3693             :     PLUMED_GCH_TRY
    3694             :     {
    3695             :       for (; ! (curr == new_end); ++curr)
    3696             :         construct (curr, g ());
    3697             :     }
    3698             :     PLUMED_GCH_CATCH (...)
    3699             :     {
    3700             :       destroy_range (begin_ptr (), curr);
    3701             :       if (has_allocation ())
    3702             :         deallocate (data_ptr (), get_capacity ());
    3703             :       PLUMED_GCH_THROW;
    3704             :     }
    3705             :     set_size (count);
    3706             :   }
    3707             : 
    3708             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    3709             :   template <std::input_iterator InputIt>
    3710             : #else
    3711             :   template <typename InputIt>
    3712             : #endif
    3713             :   PLUMED_GCH_CPP20_CONSTEXPR
    3714             :   small_vector_base (InputIt first, InputIt last, std::input_iterator_tag,
    3715             :                      const alloc_ty& alloc)
    3716             :     : small_vector_base (alloc)
    3717             :   {
    3718             :     using iterator_cat = typename std::iterator_traits<InputIt>::iterator_category;
    3719             :     append_range (first, last, iterator_cat { });
    3720             :   }
    3721             : 
    3722             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    3723             :   template <std::forward_iterator ForwardIt>
    3724             : #else
    3725             :   template <typename ForwardIt>
    3726             : #endif
    3727             :   PLUMED_GCH_CPP20_CONSTEXPR
    3728             :   small_vector_base (ForwardIt first, ForwardIt last, std::forward_iterator_tag,
    3729             :                      const alloc_ty& alloc)
    3730             :     : alloc_interface (alloc)
    3731             :   {
    3732             :     size_ty count = external_range_length (first, last);
    3733             :     if (InlineCapacity < count)
    3734             :     {
    3735             :       set_data_ptr (unchecked_allocate (count));
    3736             :       set_capacity (count);
    3737             :       PLUMED_GCH_TRY
    3738             :       {
    3739             :         uninitialized_copy (first, last, begin_ptr ());
    3740             :       }
    3741             :       PLUMED_GCH_CATCH (...)
    3742             :       {
    3743             :         deallocate (data_ptr (), get_capacity ());
    3744             :         PLUMED_GCH_THROW;
    3745             :       }
    3746             :     }
    3747             :     else
    3748             :     {
    3749             :       set_to_inline_storage ();
    3750             :       uninitialized_copy (first, last, begin_ptr ());
    3751             :     }
    3752             : 
    3753             :     set_size (count);
    3754             :   }
    3755             : 
    3756             :   PLUMED_GCH_CPP20_CONSTEXPR
    3757             :   ~small_vector_base (void) noexcept
    3758             :   {
    3759             :     assert (InlineCapacity <= get_capacity () && "Invalid capacity.");
    3760     1428222 :     wipe ();
    3761             :   }
    3762             : 
    3763             : protected:
    3764             : 
    3765             :   PLUMED_GCH_CPP20_CONSTEXPR
    3766             :   void
    3767             :   set_to_inline_storage (void)
    3768             :   {
    3769             :     set_capacity (InlineCapacity);
    3770             : #ifdef PLUMED_GCH_LIB_IS_CONSTANT_EVALUATED
    3771             :     if (std::is_constant_evaluated ())
    3772             :       return set_data_ptr (alloc_interface::allocate (InlineCapacity));
    3773             : #endif
    3774             :     set_data_ptr (storage_ptr ());
    3775        3738 :   }
    3776             : 
    3777             :   PLUMED_GCH_CPP20_CONSTEXPR
    3778             :   void
    3779             :   assign_with_copies (size_ty count, const value_ty& val)
    3780             :   {
    3781             :     if (get_capacity () < count)
    3782             :     {
    3783             :       size_ty new_capacity = checked_calculate_new_capacity (count);
    3784             :       ptr     new_begin    = unchecked_allocate (new_capacity);
    3785             : 
    3786             :       PLUMED_GCH_TRY
    3787             :       {
    3788             :         uninitialized_fill (new_begin, unchecked_next (new_begin, count), val);
    3789             :       }
    3790             :       PLUMED_GCH_CATCH (...)
    3791             :       {
    3792             :         deallocate (new_begin, new_capacity);
    3793             :         PLUMED_GCH_THROW;
    3794             :       }
    3795             : 
    3796             :       reset_data (new_begin, new_capacity, count);
    3797             :     }
    3798             :     else if (get_size () < count)
    3799             :     {
    3800             :       std::fill (begin_ptr (), end_ptr (), val);
    3801             :       uninitialized_fill (end_ptr (), unchecked_next (begin_ptr (), count), val);
    3802             :       set_size (count);
    3803             :     }
    3804             :     else
    3805             :       erase_range (std::fill_n (begin_ptr (), count, val), end_ptr ());
    3806             :   }
    3807             : 
    3808             :   template <typename InputIt,
    3809             :             typename std::enable_if<std::is_assignable<
    3810             :                                       value_ty&,
    3811             :                                       decltype (*std::declval<InputIt> ())>::value>::type * = nullptr>
    3812             :   PLUMED_GCH_CPP20_CONSTEXPR
    3813             :   void
    3814             :   assign_with_range (InputIt first, InputIt last, std::input_iterator_tag)
    3815             :   {
    3816             :     using iterator_cat = typename std::iterator_traits<InputIt>::iterator_category;
    3817             : 
    3818             :     ptr curr = begin_ptr ();
    3819             :     for (; ! (end_ptr () == curr || first == last); ++curr, static_cast<void> (++first))
    3820             :       *curr = *first;
    3821             : 
    3822             :     if (first == last)
    3823             :       erase_to_end (curr);
    3824             :     else
    3825             :       append_range (first, last, iterator_cat { });
    3826             :   }
    3827             : 
    3828             :   template <typename ForwardIt,
    3829             :             typename std::enable_if<std::is_assignable<
    3830             :                                       value_ty&,
    3831             :                                       decltype (*std::declval<ForwardIt> ())>::value>::type * = nullptr>
    3832             :   PLUMED_GCH_CPP20_CONSTEXPR
    3833             :   void
    3834             :   assign_with_range (ForwardIt first, ForwardIt last, std::forward_iterator_tag)
    3835             :   {
    3836             :     const size_ty count = external_range_length (first, last);
    3837             :     if (get_capacity () < count)
    3838             :     {
    3839             :       size_ty new_capacity = checked_calculate_new_capacity (count);
    3840             :       ptr     new_begin    = unchecked_allocate (new_capacity);
    3841             : 
    3842             :       PLUMED_GCH_TRY
    3843             :       {
    3844             :         uninitialized_copy (first, last, new_begin);
    3845             :       }
    3846             :       PLUMED_GCH_CATCH (...)
    3847             :       {
    3848             :         deallocate (new_begin, new_capacity);
    3849             :         PLUMED_GCH_THROW;
    3850             :       }
    3851             : 
    3852             :       reset_data (new_begin, new_capacity, count);
    3853             :     }
    3854             :     else if (get_size () < count)
    3855             :     {
    3856             :       ForwardIt pivot = copy_n_return_in (first, get_size (), begin_ptr ());
    3857             :       uninitialized_copy (pivot, last, end_ptr ());
    3858             :       set_size (count);
    3859             :     }
    3860             :     else
    3861             :       erase_range (copy_range (first, last, begin_ptr ()), end_ptr ());
    3862             :   }
    3863             : 
    3864             :   template <typename InputIt,
    3865             :             typename std::enable_if<! std::is_assignable<
    3866             :                                       value_ty&,
    3867             :                                       decltype (*std::declval<InputIt> ())>::value>::type * = nullptr>
    3868             :   PLUMED_GCH_CPP20_CONSTEXPR
    3869             :   void
    3870             :   assign_with_range (InputIt first, InputIt last, std::input_iterator_tag)
    3871             :   {
    3872             :     using iterator_cat = typename std::iterator_traits<InputIt>::iterator_category;
    3873             : 
    3874             :     // If not assignable then destroy all elements and append.
    3875             :     erase_all ();
    3876             :     append_range (first, last, iterator_cat { });
    3877             :   }
    3878             : 
    3879             :   // Ie. move-if-noexcept.
    3880             :   struct strong_exception_policy
    3881             :   { };
    3882             : 
    3883             :   template <typename Policy = void, typename V = value_ty,
    3884             :             typename std::enable_if<is_explicitly_move_insertable<V>::value
    3885             :                                     &&  (! std::is_same<Policy, strong_exception_policy>::value
    3886             :                                          ||  relocate_with_move<V>::value),
    3887             :                                     bool>::type = true>
    3888             :   PLUMED_GCH_CPP20_CONSTEXPR
    3889             :   ptr
    3890             :   uninitialized_move (ptr first, ptr last, ptr d_first)
    3891             :   noexcept (std::is_nothrow_move_constructible<value_ty>::value)
    3892             :   {
    3893             :     return uninitialized_copy (std::make_move_iterator (first),
    3894             :                                std::make_move_iterator (last),
    3895             :                                d_first);
    3896             :   }
    3897             : 
    3898             :   template <typename Policy = void, typename V = value_ty,
    3899             :             typename std::enable_if<! is_explicitly_move_insertable<V>::value
    3900             :                                     ||  (  std::is_same<Policy, strong_exception_policy>::value
    3901             :                                         &&! relocate_with_move<V>::value),
    3902             :                                     bool>::type = false>
    3903             :   PLUMED_GCH_CPP20_CONSTEXPR
    3904             :   ptr
    3905             :   uninitialized_move (ptr first, ptr last, ptr d_first)
    3906             :   noexcept (alloc_interface::template is_uninitialized_memcpyable_iterator<ptr>::value)
    3907             :   {
    3908             :     return uninitialized_copy (first, last, d_first);
    3909             :   }
    3910             : 
    3911             :   PLUMED_GCH_CPP20_CONSTEXPR
    3912             :   ptr
    3913             :   shift_into_uninitialized (ptr pos, size_ty n_shift)
    3914             :   {
    3915             :     // Shift elements over to the right into uninitialized space.
    3916             :     // Returns the start of the shifted range.
    3917             :     // Precondition: shift < end_ptr () - pos
    3918             :     assert (n_shift != 0 && "The value of `n_shift` should not be 0.");
    3919             : 
    3920             :     const ptr original_end = end_ptr ();
    3921             :     const ptr pivot        = unchecked_prev (original_end, n_shift);
    3922             : 
    3923             :     uninitialized_move (pivot, original_end, original_end);
    3924             :     increase_size (n_shift);
    3925             :     return move_right (pos, pivot, original_end);
    3926             :   }
    3927             : 
    3928             :   template <typename ...Args>
    3929             :   PLUMED_GCH_CPP20_CONSTEXPR
    3930             :   ptr
    3931     2150913 :   append_element (Args&&... args)
    3932             :   {
    3933     2150913 :     if (get_size () < get_capacity ())
    3934     2149600 :           return emplace_into_current_end (std::forward<Args> (args)...);
    3935        1313 :     return emplace_into_reallocation_end (std::forward<Args> (args)...);
    3936             :   }
    3937             : 
    3938             :   PLUMED_GCH_CPP20_CONSTEXPR
    3939             :   ptr
    3940             :   append_copies (size_ty count, const value_ty& val)
    3941             :   {
    3942             :     if (num_uninitialized () < count)
    3943             :     {
    3944             :       // Reallocate.
    3945             :       if (get_max_size () - get_size () < count)
    3946             :         throw_allocation_size_error ();
    3947             : 
    3948             :       size_ty original_size = get_size ();
    3949             :       size_ty new_size      = get_size () + count;
    3950             : 
    3951             :       // The check is handled by the if-guard.
    3952             :       size_ty new_capacity = unchecked_calculate_new_capacity (new_size);
    3953             :       ptr     new_data_ptr = unchecked_allocate (new_capacity, allocation_end_ptr ());
    3954             :       ptr     new_last     = unchecked_next (new_data_ptr, original_size);
    3955             : 
    3956             :       PLUMED_GCH_TRY
    3957             :       {
    3958             :         new_last = uninitialized_fill (new_last, unchecked_next (new_last, count), val);
    3959             :         uninitialized_move (begin_ptr (), end_ptr (), new_data_ptr);
    3960             :       }
    3961             :       PLUMED_GCH_CATCH (...)
    3962             :       {
    3963             :         destroy_range (unchecked_next (new_data_ptr, original_size), new_last);
    3964             :         deallocate (new_data_ptr, new_capacity);
    3965             :         PLUMED_GCH_THROW;
    3966             :       }
    3967             : 
    3968             :       reset_data (new_data_ptr, new_capacity, new_size);
    3969             :       return unchecked_next (new_data_ptr, original_size);
    3970             :     }
    3971             :     else
    3972             :     {
    3973             :       const ptr ret = end_ptr ();
    3974             :       uninitialized_fill (ret, unchecked_next (ret, count), val);
    3975             :       increase_size (count);
    3976             :       return ret;
    3977             :     }
    3978             :   }
    3979             : 
    3980             :   template <typename MovePolicy, typename InputIt,
    3981             :             typename std::enable_if<
    3982             :               std::is_same<MovePolicy, strong_exception_policy>::value, bool>::type = true>
    3983             :   PLUMED_GCH_CPP20_CONSTEXPR
    3984             :   ptr
    3985             :   append_range (InputIt first, InputIt last, std::input_iterator_tag)
    3986             :   {
    3987             :     // Append with a strong exception guarantee.
    3988             :     size_ty original_size = get_size ();
    3989             :     for (; ! (first == last); ++first)
    3990             :     {
    3991             :       PLUMED_GCH_TRY
    3992             :       {
    3993             :         append_element (*first);
    3994             :       }
    3995             :       PLUMED_GCH_CATCH (...)
    3996             :       {
    3997             :         erase_range (unchecked_next (begin_ptr (), original_size), end_ptr ());
    3998             :         PLUMED_GCH_THROW;
    3999             :       }
    4000             :     }
    4001             :     return unchecked_next (begin_ptr (), original_size);
    4002             :   }
    4003             : 
    4004             :   template <typename MovePolicy = void, typename InputIt,
    4005             :             typename std::enable_if<
    4006             :               ! std::is_same<MovePolicy, strong_exception_policy>::value, bool>::type = false>
    4007             :   PLUMED_GCH_CPP20_CONSTEXPR
    4008             :   ptr
    4009             :   append_range (InputIt first, InputIt last, std::input_iterator_tag)
    4010             :   {
    4011             :     size_ty original_size = get_size ();
    4012             :     for (; ! (first == last); ++first)
    4013             :       append_element (*first);
    4014             :     return unchecked_next (begin_ptr (), original_size);
    4015             :   }
    4016             : 
    4017             :   template <typename MovePolicy = void, typename ForwardIt>
    4018             :   PLUMED_GCH_CPP20_CONSTEXPR
    4019             :   ptr
    4020             :   append_range (ForwardIt first, ForwardIt last, std::forward_iterator_tag)
    4021             :   {
    4022             :     const size_ty num_insert = external_range_length (first, last);
    4023             : 
    4024             :     if (num_uninitialized () < num_insert)
    4025             :     {
    4026             :       // Reallocate.
    4027             :       if (get_max_size () - get_size () < num_insert)
    4028             :         throw_allocation_size_error ();
    4029             : 
    4030             :       size_ty original_size = get_size ();
    4031             :       size_ty new_size      = get_size () + num_insert;
    4032             : 
    4033             :       // The check is handled by the if-guard.
    4034             :       size_ty new_capacity = unchecked_calculate_new_capacity (new_size);
    4035             :       ptr     new_data_ptr = unchecked_allocate (new_capacity, allocation_end_ptr ());
    4036             :       ptr     new_last     = unchecked_next (new_data_ptr, original_size);
    4037             : 
    4038             :       PLUMED_GCH_TRY
    4039             :       {
    4040             :         new_last = uninitialized_copy (first, last, new_last);
    4041             :         uninitialized_move<MovePolicy> (begin_ptr (), end_ptr (), new_data_ptr);
    4042             :       }
    4043             :       PLUMED_GCH_CATCH (...)
    4044             :       {
    4045             :         destroy_range (unchecked_next (new_data_ptr, original_size), new_last);
    4046             :         deallocate (new_data_ptr, new_capacity);
    4047             :         PLUMED_GCH_THROW;
    4048             :       }
    4049             : 
    4050             :       reset_data (new_data_ptr, new_capacity, new_size);
    4051             :       return unchecked_next (new_data_ptr, original_size);
    4052             :     }
    4053             :     else
    4054             :     {
    4055             :       ptr ret = end_ptr ();
    4056             :       uninitialized_copy (first, last, ret);
    4057             :       increase_size (num_insert);
    4058             :       return ret;
    4059             :     }
    4060             :   }
    4061             : 
    4062             :   template <typename ...Args>
    4063             :   PLUMED_GCH_CPP20_CONSTEXPR
    4064             :   ptr
    4065             :   emplace_at (ptr pos, Args&&... args)
    4066             :   {
    4067             :     assert (get_size () <= get_capacity () && "size was greater than capacity");
    4068             : 
    4069             :     if (get_size () < get_capacity ())
    4070             :       return emplace_into_current (pos, std::forward<Args> (args)...);
    4071             :     return emplace_into_reallocation (pos, std::forward<Args> (args)...);
    4072             :   }
    4073             : 
    4074             :   PLUMED_GCH_CPP20_CONSTEXPR
    4075             :   ptr
    4076             :   insert_copies (ptr pos, size_ty count, const value_ty& val)
    4077             :   {
    4078             :     if (0 == count)
    4079             :       return pos;
    4080             : 
    4081             :     if (end_ptr () == pos)
    4082             :     {
    4083             :       if (1 == count)
    4084             :         return append_element (val);
    4085             :       return append_copies (count, val);
    4086             :     }
    4087             : 
    4088             :     if (num_uninitialized () < count)
    4089             :     {
    4090             :       // Reallocate.
    4091             :       if (get_max_size () - get_size () < count)
    4092             :         throw_allocation_size_error ();
    4093             : 
    4094             :       const size_ty offset = internal_range_length (begin_ptr (), pos);
    4095             : 
    4096             :       const size_ty new_size = get_size () + count;
    4097             : 
    4098             :       // The check is handled by the if-guard.
    4099             :       const size_ty new_capacity = unchecked_calculate_new_capacity (new_size);
    4100             :       ptr new_data_ptr           = unchecked_allocate (new_capacity, allocation_end_ptr ());
    4101             :       ptr new_first              = unchecked_next (new_data_ptr, offset);
    4102             :       ptr new_last               = new_first;
    4103             : 
    4104             :       PLUMED_GCH_TRY
    4105             :       {
    4106             :         uninitialized_fill (new_first, unchecked_next (new_first, count), val);
    4107             :         unchecked_advance  (new_last, count);
    4108             : 
    4109             :         uninitialized_move (begin_ptr (), pos, new_data_ptr);
    4110             :         new_first = new_data_ptr;
    4111             :         uninitialized_move (pos, end_ptr (), new_last);
    4112             :       }
    4113             :       PLUMED_GCH_CATCH (...)
    4114             :       {
    4115             :         destroy_range (new_first, new_last);
    4116             :         deallocate (new_data_ptr, new_capacity);
    4117             :         PLUMED_GCH_THROW;
    4118             :       }
    4119             : 
    4120             :       reset_data (new_data_ptr, new_capacity, new_size);
    4121             :       return unchecked_next (begin_ptr (), offset);
    4122             :     }
    4123             :     else
    4124             :     {
    4125             :       // If we have fewer to insert than tailing elements after `pos`, we shift into
    4126             :       // uninitialized and then copy over.
    4127             : 
    4128             :       const size_ty tail_size = internal_range_length (pos, end_ptr ());
    4129             :       if (tail_size < count)
    4130             :       {
    4131             :         // The number inserted is larger than the number after `pos`,
    4132             :         // so part of the input will be used to construct new elements,
    4133             :         // and another part of it will assign existing ones.
    4134             :         // In order:
    4135             :         //   Construct new elements immediately after end_ptr () using the input.
    4136             :         //   Move-construct existing elements over to the tail.
    4137             :         //   Assign existing elements using the input.
    4138             : 
    4139             :         ptr original_end = end_ptr ();
    4140             : 
    4141             :         // Place a portion of the input into the uninitialized section.
    4142             :         size_ty num_val_tail = count - tail_size;
    4143             : 
    4144             : #ifdef PLUMED_GCH_LIB_IS_CONSTANT_EVALUATED
    4145             :         if (std::is_constant_evaluated ())
    4146             :         {
    4147             :           uninitialized_fill (end_ptr (), unchecked_next (end_ptr (), num_val_tail), val);
    4148             :           increase_size (num_val_tail);
    4149             : 
    4150             :           const heap_temporary tmp (*this, val);
    4151             : 
    4152             :           uninitialized_move (pos, original_end, end_ptr ());
    4153             :           increase_size (tail_size);
    4154             : 
    4155             :           std::fill_n (pos, tail_size, tmp.get ());
    4156             : 
    4157             :           return pos;
    4158             :         }
    4159             : #endif
    4160             : 
    4161             :         uninitialized_fill (end_ptr (), unchecked_next (end_ptr (), num_val_tail), val);
    4162             :         increase_size (num_val_tail);
    4163             : 
    4164             :         PLUMED_GCH_TRY
    4165             :         {
    4166             :           // We need to handle possible aliasing here.
    4167             :           const stack_temporary tmp (*this, val);
    4168             : 
    4169             :           // Now, move the tail to the end.
    4170             :           uninitialized_move (pos, original_end, end_ptr ());
    4171             :           increase_size (tail_size);
    4172             : 
    4173             :           PLUMED_GCH_TRY
    4174             :           {
    4175             :             // Finally, try to copy the rest of the elements over.
    4176             :             std::fill_n (pos, tail_size, tmp.get ());
    4177             :           }
    4178             :           PLUMED_GCH_CATCH (...)
    4179             :           {
    4180             :             // Attempt to roll back and destroy the tail if we fail.
    4181             :             ptr inserted_end = unchecked_prev (end_ptr (), tail_size);
    4182             :             move_left (inserted_end, end_ptr (), pos);
    4183             :             destroy_range (inserted_end, end_ptr ());
    4184             :             decrease_size (tail_size);
    4185             :             PLUMED_GCH_THROW;
    4186             :           }
    4187             :         }
    4188             :         PLUMED_GCH_CATCH (...)
    4189             :         {
    4190             :           // Destroy the elements constructed from the input.
    4191             :           destroy_range (original_end, end_ptr ());
    4192             :           decrease_size (internal_range_length (original_end, end_ptr ()));
    4193             :           PLUMED_GCH_THROW;
    4194             :         }
    4195             :       }
    4196             :       else
    4197             :       {
    4198             : #ifdef PLUMED_GCH_LIB_IS_CONSTANT_EVALUATED
    4199             :         if (std::is_constant_evaluated ())
    4200             :         {
    4201             :           const heap_temporary tmp (*this, val);
    4202             : 
    4203             :           ptr inserted_end = shift_into_uninitialized (pos, count);
    4204             :           std::fill (pos, inserted_end, tmp.get ());
    4205             : 
    4206             :           return pos;
    4207             :         }
    4208             : #endif
    4209             :         const stack_temporary tmp (*this, val);
    4210             : 
    4211             :         ptr inserted_end = shift_into_uninitialized (pos, count);
    4212             : 
    4213             :         // Attempt to copy over the elements.
    4214             :         // If we fail we'll attempt a full roll-back.
    4215             :         PLUMED_GCH_TRY
    4216             :         {
    4217             :           std::fill (pos, inserted_end, tmp.get ());
    4218             :         }
    4219             :         PLUMED_GCH_CATCH (...)
    4220             :         {
    4221             :           ptr original_end = move_left (inserted_end, end_ptr (), pos);
    4222             :           destroy_range (original_end, end_ptr ());
    4223             :           decrease_size (count);
    4224             :           PLUMED_GCH_THROW;
    4225             :         }
    4226             :       }
    4227             :       return pos;
    4228             :     }
    4229             :   }
    4230             : 
    4231             :   template <typename ForwardIt>
    4232             :   PLUMED_GCH_CPP20_CONSTEXPR
    4233             :   ptr
    4234             :   insert_range_helper (ptr pos, ForwardIt first, ForwardIt last)
    4235             :   {
    4236             :     assert (! (first == last) && "The range should not be empty.");
    4237             :     assert (! (end_ptr () == pos) && "`pos` should not be at the end.");
    4238             : 
    4239             :     const size_ty num_insert = external_range_length (first, last);
    4240             :     if (num_uninitialized () < num_insert)
    4241             :     {
    4242             :       // Reallocate.
    4243             :       if (get_max_size () - get_size () < num_insert)
    4244             :         throw_allocation_size_error ();
    4245             : 
    4246             :       const size_ty offset   = internal_range_length (begin_ptr (), pos);
    4247             :       const size_ty new_size = get_size () + num_insert;
    4248             : 
    4249             :       // The check is handled by the if-guard.
    4250             :       const size_ty new_capacity = unchecked_calculate_new_capacity (new_size);
    4251             :       const ptr     new_data_ptr = unchecked_allocate (new_capacity, allocation_end_ptr ());
    4252             :       ptr           new_first    = unchecked_next (new_data_ptr, offset);
    4253             :       ptr           new_last     = new_first;
    4254             : 
    4255             :       PLUMED_GCH_TRY
    4256             :       {
    4257             :         uninitialized_copy (first, last, new_first);
    4258             :         unchecked_advance  (new_last, num_insert);
    4259             : 
    4260             :         uninitialized_move (begin_ptr (), pos, new_data_ptr);
    4261             :         new_first = new_data_ptr;
    4262             :         uninitialized_move (pos, end_ptr (), new_last);
    4263             :       }
    4264             :       PLUMED_GCH_CATCH (...)
    4265             :       {
    4266             :         destroy_range (new_first, new_last);
    4267             :         deallocate (new_data_ptr, new_capacity);
    4268             :         PLUMED_GCH_THROW;
    4269             :       }
    4270             : 
    4271             :       reset_data (new_data_ptr, new_capacity, new_size);
    4272             :       return unchecked_next (begin_ptr (), offset);
    4273             :     }
    4274             :     else
    4275             :     {
    4276             :       // if we have fewer to insert than tailing elements after
    4277             :       // `pos` we shift into uninitialized and then copy over
    4278             :       const size_ty tail_size = internal_range_length (pos, end_ptr ());
    4279             :       if (tail_size < num_insert)
    4280             :       {
    4281             :         // Use the same method as insert_copies.
    4282             :         ptr original_end = end_ptr ();
    4283             :         ForwardIt pivot  = unchecked_next (first, tail_size);
    4284             : 
    4285             :         // Place a portion of the input into the uninitialized section.
    4286             :         uninitialized_copy (pivot, last, end_ptr ());
    4287             :         increase_size (num_insert - tail_size);
    4288             : 
    4289             :         PLUMED_GCH_TRY
    4290             :         {
    4291             :           // Now move the tail to the end.
    4292             :           uninitialized_move (pos, original_end, end_ptr ());
    4293             :           increase_size (tail_size);
    4294             : 
    4295             :           PLUMED_GCH_TRY
    4296             :           {
    4297             :             // Finally, try to copy the rest of the elements over.
    4298             :             copy_range (first, pivot, pos);
    4299             :           }
    4300             :           PLUMED_GCH_CATCH (...)
    4301             :           {
    4302             :             // Attempt to roll back and destroy the tail if we fail.
    4303             :             ptr inserted_end = unchecked_prev (end_ptr (), tail_size);
    4304             :             move_left (inserted_end, end_ptr (), pos);
    4305             :             destroy_range (inserted_end, end_ptr ());
    4306             :             decrease_size (tail_size);
    4307             :             PLUMED_GCH_THROW;
    4308             :           }
    4309             :         }
    4310             :         PLUMED_GCH_CATCH (...)
    4311             :         {
    4312             :           // If we throw, destroy the first copy we made.
    4313             :           destroy_range (original_end, end_ptr ());
    4314             :           decrease_size (internal_range_length (original_end, end_ptr ()));
    4315             :           PLUMED_GCH_THROW;
    4316             :         }
    4317             :       }
    4318             :       else
    4319             :       {
    4320             :         shift_into_uninitialized (pos, num_insert);
    4321             : 
    4322             :         // Attempt to copy over the elements.
    4323             :         // If we fail we'll attempt a full roll-back.
    4324             :         PLUMED_GCH_TRY
    4325             :         {
    4326             :           copy_range (first, last, pos);
    4327             :         }
    4328             :         PLUMED_GCH_CATCH (...)
    4329             :         {
    4330             :           ptr inserted_end = unchecked_next (pos, num_insert);
    4331             :           ptr original_end = move_left (inserted_end, end_ptr (), pos);
    4332             :           destroy_range (original_end, end_ptr ());
    4333             :           decrease_size (num_insert);
    4334             :           PLUMED_GCH_THROW;
    4335             :         }
    4336             :       }
    4337             :       return pos;
    4338             :     }
    4339             :   }
    4340             : 
    4341             :   template <typename InputIt>
    4342             :   PLUMED_GCH_CPP20_CONSTEXPR
    4343             :   ptr
    4344             :   insert_range (ptr pos, InputIt first, InputIt last, std::input_iterator_tag)
    4345             :   {
    4346             :     assert (! (first == last) && "The range should not be empty.");
    4347             : 
    4348             :     // Ensure we use this specific overload to give a strong exception guarantee for 1 element.
    4349             :     if (end_ptr () == pos)
    4350             :       return append_range (first, last, std::input_iterator_tag { });
    4351             : 
    4352             :     using iterator_cat = typename std::iterator_traits<InputIt>::iterator_category;
    4353             :     small_vector_base tmp (first, last, iterator_cat { }, allocator_ref ());
    4354             : 
    4355             :     return insert_range_helper (
    4356             :              pos,
    4357             :              std::make_move_iterator (tmp.begin_ptr ()),
    4358             :              std::make_move_iterator (tmp.end_ptr ()));
    4359             :   }
    4360             : 
    4361             :   template <typename ForwardIt>
    4362             :   PLUMED_GCH_CPP20_CONSTEXPR
    4363             :   ptr
    4364             :   insert_range (ptr pos, ForwardIt first, ForwardIt last, std::forward_iterator_tag)
    4365             :   {
    4366             :     if (! (end_ptr () == pos))
    4367             :       return insert_range_helper (pos, first, last);
    4368             : 
    4369             :     if (unchecked_next (first) == last)
    4370             :       return append_element (*first);
    4371             : 
    4372             :     using iterator_cat = typename std::iterator_traits<ForwardIt>::iterator_category;
    4373             :     return append_range (first, last, iterator_cat { });
    4374             :   }
    4375             : 
    4376             :   template <typename ...Args>
    4377             :   PLUMED_GCH_CPP20_CONSTEXPR
    4378             :   ptr
    4379     2149600 :   emplace_into_current_end (Args&&... args)
    4380             :   {
    4381     2149600 :     construct (end_ptr (), std::forward<Args> (args)...);
    4382             :     increase_size (1);
    4383     2149600 :     return unchecked_prev (end_ptr ());
    4384             :   }
    4385             : 
    4386             :   template <typename V = value_ty,
    4387             :             typename std::enable_if<
    4388             :               std::is_nothrow_move_constructible<V>::value>::type * = nullptr>
    4389             :   PLUMED_GCH_CPP20_CONSTEXPR
    4390             :   ptr
    4391             :   emplace_into_current (ptr pos, value_ty&& val)
    4392             :   {
    4393             :     if (pos == end_ptr ())
    4394             :       return emplace_into_current_end (std::move (val));
    4395             : 
    4396             :     // In the special case of value_ty&& we don't make a copy because behavior is unspecified
    4397             :     // when it is an internal element. Hence, we'll take the opportunity to optimize and assume
    4398             :     // that it isn't an internal element.
    4399             :     shift_into_uninitialized (pos, 1);
    4400             :     destroy (pos);
    4401             :     construct (pos, std::move (val));
    4402             :     return pos;
    4403             :   }
    4404             : 
    4405             :   template <typename ...Args>
    4406             :   PLUMED_GCH_CPP20_CONSTEXPR
    4407             :   ptr
    4408             :   emplace_into_current (ptr pos, Args&&... args)
    4409             :   {
    4410             :     if (pos == end_ptr ())
    4411             :       return emplace_into_current_end (std::forward<Args> (args)...);
    4412             : 
    4413             : #ifdef PLUMED_GCH_LIB_IS_CONSTANT_EVALUATED
    4414             :     if (std::is_constant_evaluated ())
    4415             :     {
    4416             :       heap_temporary tmp (*this, std::forward<Args> (args)...);
    4417             :       shift_into_uninitialized (pos, 1);
    4418             :       *pos = tmp.release ();
    4419             :       return pos;
    4420             :     }
    4421             : #endif
    4422             : 
    4423             :     // This is necessary because of possible aliasing.
    4424             :     stack_temporary tmp (*this, std::forward<Args> (args)...);
    4425             :     shift_into_uninitialized (pos, 1);
    4426             :     *pos = tmp.release ();
    4427             :     return pos;
    4428             :   }
    4429             : 
    4430             :   template <typename ...Args>
    4431             :   PLUMED_GCH_CPP20_CONSTEXPR
    4432             :   ptr
    4433        1313 :   emplace_into_reallocation_end (Args&&... args)
    4434             :   {
    4435             :     // Appending; strong exception guarantee.
    4436        1313 :     if (get_max_size () == get_size ())
    4437           0 :       throw_allocation_size_error ();
    4438             : 
    4439        1313 :     const size_ty new_size = get_size () + 1;
    4440             : 
    4441             :     // The check is handled by the if-guard.
    4442             :     const size_ty new_capacity = unchecked_calculate_new_capacity (new_size);
    4443        1313 :     const ptr     new_data_ptr = unchecked_allocate (new_capacity, allocation_end_ptr ());
    4444        1313 :     const ptr     emplace_pos  = unchecked_next (new_data_ptr, get_size ());
    4445             : 
    4446             :     PLUMED_GCH_TRY
    4447             :     {
    4448             :       construct (emplace_pos, std::forward<Args> (args)...);
    4449             :       PLUMED_GCH_TRY
    4450             :       {
    4451        1313 :         uninitialized_move<strong_exception_policy> (begin_ptr (), end_ptr (), new_data_ptr);
    4452             :       }
    4453             :       PLUMED_GCH_CATCH (...)
    4454             :       {
    4455             :         destroy (emplace_pos);
    4456             :         PLUMED_GCH_THROW;
    4457             :       }
    4458             :     }
    4459             :     PLUMED_GCH_CATCH (...)
    4460             :     {
    4461             :       deallocate (new_data_ptr, new_capacity);
    4462             :       PLUMED_GCH_THROW;
    4463             :     }
    4464             : 
    4465             :     reset_data (new_data_ptr, new_capacity, new_size);
    4466        1313 :     return emplace_pos;
    4467             :   }
    4468             : 
    4469             :   template <typename ...Args>
    4470             :   PLUMED_GCH_CPP20_CONSTEXPR
    4471             :   ptr
    4472             :   emplace_into_reallocation (ptr pos, Args&&... args)
    4473             :   {
    4474             :     const size_ty offset = internal_range_length (begin_ptr (), pos);
    4475             :     if (offset == get_size ())
    4476             :       return emplace_into_reallocation_end (std::forward<Args> (args)...);
    4477             : 
    4478             :     if (get_max_size () == get_size ())
    4479             :       throw_allocation_size_error ();
    4480             : 
    4481             :     const size_ty new_size = get_size () + 1;
    4482             : 
    4483             :     // The check is handled by the if-guard.
    4484             :     const size_ty new_capacity = unchecked_calculate_new_capacity (new_size);
    4485             :     const ptr     new_data_ptr = unchecked_allocate (new_capacity, allocation_end_ptr ());
    4486             :     ptr           new_first    = unchecked_next (new_data_ptr, offset);
    4487             :     ptr           new_last     = new_first;
    4488             : 
    4489             :     PLUMED_GCH_TRY
    4490             :     {
    4491             :       construct (new_first, std::forward<Args> (args)...);
    4492             :       unchecked_advance (new_last, 1);
    4493             : 
    4494             :       uninitialized_move (begin_ptr (), pos, new_data_ptr);
    4495             :       new_first = new_data_ptr;
    4496             :       uninitialized_move (pos, end_ptr (), new_last);
    4497             :     }
    4498             :     PLUMED_GCH_CATCH (...)
    4499             :     {
    4500             :       destroy_range (new_first, new_last);
    4501             :       deallocate (new_data_ptr, new_capacity);
    4502             :       PLUMED_GCH_THROW;
    4503             :     }
    4504             : 
    4505             :     reset_data (new_data_ptr, new_capacity, new_size);
    4506             :     return unchecked_next (begin_ptr (), offset);
    4507             :   }
    4508             : 
    4509             :   PLUMED_GCH_CPP20_CONSTEXPR
    4510             :   ptr
    4511             :   shrink_to_size (void)
    4512             :   {
    4513             :     if (! has_allocation () || get_size () == get_capacity ())
    4514             :       return begin_ptr ();
    4515             : 
    4516             :     // The rest runs only if allocated.
    4517             : 
    4518             :     size_ty new_capacity;
    4519             :     ptr     new_data_ptr;
    4520             : 
    4521             :     if (InlineCapacity < get_size ())
    4522             :     {
    4523             :       new_capacity = get_size ();
    4524             :       new_data_ptr = unchecked_allocate (new_capacity, allocation_end_ptr ());
    4525             :     }
    4526             :     else
    4527             :     {
    4528             :       // We move to inline storage.
    4529             :       new_capacity = InlineCapacity;
    4530             : #ifdef PLUMED_GCH_LIB_IS_CONSTANT_EVALUATED
    4531             :       if (std::is_constant_evaluated ())
    4532             :         new_data_ptr = alloc_interface::allocate (InlineCapacity);
    4533             :       else
    4534             :         new_data_ptr = storage_ptr ();
    4535             : #else
    4536             :       new_data_ptr = storage_ptr ();
    4537             : #endif
    4538             :     }
    4539             : 
    4540             :     uninitialized_move (begin_ptr (), end_ptr (), new_data_ptr);
    4541             : 
    4542             :     destroy_range (begin_ptr (), end_ptr ());
    4543             :     deallocate (data_ptr (), get_capacity ());
    4544             : 
    4545             :     set_data_ptr (new_data_ptr);
    4546             :     set_capacity (new_capacity);
    4547             : 
    4548             :     return begin_ptr ();
    4549             :   }
    4550             : 
    4551             :   template <typename ...ValueT>
    4552             :   PLUMED_GCH_CPP20_CONSTEXPR
    4553             :   void
    4554             :   resize_with (size_ty new_size, const ValueT&... val)
    4555             :   {
    4556             :     // ValueT... should either be value_ty or empty.
    4557             : 
    4558             :     if (new_size == 0)
    4559             :       erase_all ();
    4560             : 
    4561             :     if (get_capacity () < new_size)
    4562             :     {
    4563             :       // Reallocate.
    4564             : 
    4565             :       if (get_max_size () < new_size)
    4566             :         throw_allocation_size_error ();
    4567             : 
    4568             :       const size_ty original_size = get_size ();
    4569             : 
    4570             :       // The check is handled by the if-guard.
    4571             :       const size_ty new_capacity = unchecked_calculate_new_capacity (new_size);
    4572             :       ptr           new_data_ptr = unchecked_allocate (new_capacity, allocation_end_ptr ());
    4573             :       ptr           new_last     = unchecked_next (new_data_ptr, original_size);
    4574             : 
    4575             :       PLUMED_GCH_TRY
    4576             :       {
    4577             :         new_last = uninitialized_fill (
    4578             :           new_last,
    4579             :           unchecked_next (new_data_ptr, new_size),
    4580             :           val...);
    4581             : 
    4582             :         // Strong exception guarantee.
    4583             :         uninitialized_move<strong_exception_policy> (begin_ptr (), end_ptr (), new_data_ptr);
    4584             :       }
    4585             :       PLUMED_GCH_CATCH (...)
    4586             :       {
    4587             :         destroy_range (unchecked_next (new_data_ptr, original_size), new_last);
    4588             :         deallocate (new_data_ptr, new_capacity);
    4589             :         PLUMED_GCH_THROW;
    4590             :       }
    4591             : 
    4592             :       reset_data (new_data_ptr, new_capacity, new_size);
    4593             :     }
    4594             :     else if (get_size () < new_size)
    4595             :     {
    4596             :       // Construct in the uninitialized section.
    4597             :       uninitialized_fill (end_ptr (), unchecked_next (begin_ptr (), new_size), val...);
    4598             :       set_size (new_size);
    4599             :     }
    4600             :     else
    4601             :       erase_range (unchecked_next (begin_ptr (), new_size), end_ptr ());
    4602             : 
    4603             :     // Do nothing if the count is the same as the current size.
    4604             :   }
    4605             : 
    4606             :   PLUMED_GCH_CPP20_CONSTEXPR
    4607             :   void
    4608       50163 :   request_capacity (size_ty request)
    4609             :   {
    4610       50163 :     if (request <= get_capacity ())
    4611             :       return;
    4612             : 
    4613        2344 :     size_ty new_capacity = checked_calculate_new_capacity (request);
    4614             :     ptr     new_begin    = unchecked_allocate (new_capacity);
    4615             : 
    4616             :     PLUMED_GCH_TRY
    4617             :     {
    4618        2344 :       uninitialized_move<strong_exception_policy> (begin_ptr (), end_ptr (), new_begin);
    4619             :     }
    4620             :     PLUMED_GCH_CATCH (...)
    4621             :     {
    4622             :       deallocate (new_begin, new_capacity);
    4623             :       PLUMED_GCH_THROW;
    4624             :     }
    4625             : 
    4626        2344 :     wipe ();
    4627             : 
    4628             :     set_data_ptr (new_begin);
    4629             :     set_capacity (new_capacity);
    4630             :   }
    4631             : 
    4632             :   PLUMED_GCH_CPP20_CONSTEXPR
    4633             :   ptr
    4634             :   erase_at (ptr pos)
    4635             :   {
    4636             :     move_left (unchecked_next (pos), end_ptr (), pos);
    4637             :     erase_last ();
    4638             :     return pos;
    4639             :   }
    4640             : 
    4641             :   PLUMED_GCH_CPP20_CONSTEXPR
    4642             :   void
    4643             :   erase_last (void)
    4644             :   {
    4645             :     decrease_size (1);
    4646             : 
    4647             :     // The element located at end_ptr is still alive since the size decreased.
    4648      137267 :     destroy (end_ptr ());
    4649             :   }
    4650             : 
    4651             :   PLUMED_GCH_CPP20_CONSTEXPR
    4652             :   ptr
    4653             :   erase_range (ptr first, ptr last)
    4654             :   {
    4655             :     if (! (first == last))
    4656             :       erase_to_end (move_left (last, end_ptr (), first));
    4657             :     return first;
    4658             :   }
    4659             : 
    4660             :   PLUMED_GCH_CPP20_CONSTEXPR
    4661             :   void
    4662             :   erase_to_end (ptr pos)
    4663             :   {
    4664             :     assert (0 <= (end_ptr () - pos) && "`pos` was in the uninitialized range");
    4665             :     if (size_ty change = internal_range_length (pos, end_ptr ()))
    4666             :     {
    4667             :       decrease_size (change);
    4668             :       destroy_range (pos, unchecked_next (pos, change));
    4669             :     }
    4670             :   }
    4671             : 
    4672             :   PLUMED_GCH_CPP20_CONSTEXPR
    4673             :   void
    4674             :   erase_all (void)
    4675             :   {
    4676     1509998 :     ptr curr_end = end_ptr ();
    4677             :     set_size (0);
    4678             :     destroy_range (begin_ptr (), curr_end);
    4679             :   }
    4680             : 
    4681             :   PLUMED_GCH_CPP20_CONSTEXPR
    4682             :   void
    4683             :   swap_elements (small_vector_base& other)
    4684             :   noexcept (std::is_nothrow_move_constructible<value_ty>::value
    4685             : #ifdef PLUMED_GCH_LIB_IS_SWAPPABLE
    4686             :             &&  std::is_nothrow_swappable<value_ty>::value
    4687             : #else
    4688             :             &&  detail::small_vector_adl::is_nothrow_swappable<value_ty>::value
    4689             : #endif
    4690             :            )
    4691             :   {
    4692             :     assert (get_size () <= other.get_size ());
    4693             : 
    4694             :     const ptr other_tail = std::swap_ranges (begin_ptr (), end_ptr (), other.begin_ptr ());
    4695             :     uninitialized_move (other_tail, other.end_ptr (), end_ptr ());
    4696             :     destroy_range (other_tail, other.end_ptr ());
    4697             : 
    4698             :     swap_size (other);
    4699             :   }
    4700             : 
    4701             :   PLUMED_GCH_CPP20_CONSTEXPR
    4702             :   void
    4703             :   swap_default (small_vector_base& other)
    4704             :   noexcept (std::is_nothrow_move_constructible<value_ty>::value
    4705             : #ifdef PLUMED_GCH_LIB_IS_SWAPPABLE
    4706             :             &&  std::is_nothrow_swappable<value_ty>::value
    4707             : #else
    4708             :             &&  detail::small_vector_adl::is_nothrow_swappable<value_ty>::value
    4709             : #endif
    4710             :            )
    4711             :   {
    4712             :     // This function is used when:
    4713             :     //   We are using the standard allocator.
    4714             :     //   The allocators propagate and are equal.
    4715             :     //   The allocators are always equal.
    4716             :     //   The allocators do not propagate and are equal.
    4717             :     //   The allocators propagate and are not equal.
    4718             : 
    4719             :     // Not handled:
    4720             :     //   The allocators do not propagate and are not equal.
    4721             : 
    4722             :     assert (get_capacity () <= other.get_capacity ());
    4723             : 
    4724             :     if (has_allocation ()) // Implies that `other` also has an allocation.
    4725             :       swap_allocation (other);
    4726             :     else if (other.has_allocation ())
    4727             :     {
    4728             :       // Note: This will never be constant evaluated because both are always allocated.
    4729             :       uninitialized_move (begin_ptr (), end_ptr (), other.storage_ptr ());
    4730             :       destroy_range (begin_ptr (), end_ptr ());
    4731             : 
    4732             :       set_data_ptr (other.data_ptr ());
    4733             :       set_capacity (other.get_capacity ());
    4734             : 
    4735             :       other.set_data_ptr (other.storage_ptr ());
    4736             :       other.set_capacity (InlineCapacity);
    4737             : 
    4738             :       swap_size (other);
    4739             :     }
    4740             :     else if (get_size () < other.get_size ())
    4741             :       swap_elements (other);
    4742             :     else
    4743             :       other.swap_elements (*this);
    4744             : 
    4745             :     alloc_interface::swap (other);
    4746             :   }
    4747             : 
    4748             :   PLUMED_GCH_CPP20_CONSTEXPR
    4749             :   void
    4750             :   swap_unequal_no_propagate (small_vector_base& other)
    4751             :   {
    4752             :     assert (get_capacity () <= other.get_capacity ());
    4753             : 
    4754             :     if (get_capacity () < other.get_size ())
    4755             :     {
    4756             :       // Reallocation required.
    4757             :       // We should always be able to reuse the allocation of `other`.
    4758             :       const size_ty new_capacity = unchecked_calculate_new_capacity (other.get_size ());
    4759             :       const ptr     new_data_ptr = unchecked_allocate (new_capacity, end_ptr ());
    4760             : 
    4761             :       PLUMED_GCH_TRY
    4762             :       {
    4763             :         uninitialized_move (other.begin_ptr (), other.end_ptr (), new_data_ptr);
    4764             :         PLUMED_GCH_TRY
    4765             :         {
    4766             :           destroy_range (
    4767             :             std::move (begin_ptr (), end_ptr (), other.begin_ptr ()),
    4768             :             other.end_ptr ());
    4769             :         }
    4770             :         PLUMED_GCH_CATCH (...)
    4771             :         {
    4772             :           destroy_range (new_data_ptr, unchecked_next (new_data_ptr, other.get_size ()));
    4773             :           PLUMED_GCH_THROW;
    4774             :         }
    4775             :       }
    4776             :       PLUMED_GCH_CATCH (...)
    4777             :       {
    4778             :         deallocate (new_data_ptr, new_capacity);
    4779             :         PLUMED_GCH_THROW;
    4780             :       }
    4781             : 
    4782             :       destroy_range (begin_ptr (), end_ptr ());
    4783             :       if (has_allocation ())
    4784             :         deallocate (data_ptr (), get_capacity ());
    4785             : 
    4786             :       set_data_ptr (new_data_ptr);
    4787             :       set_capacity (new_capacity);
    4788             :       swap_size (other);
    4789             :     }
    4790             :     else if (get_size () < other.get_size ())
    4791             :       swap_elements (other);
    4792             :     else
    4793             :       other.swap_elements (*this);
    4794             : 
    4795             :     // This should have no effect.
    4796             :     alloc_interface::swap (other);
    4797             :   }
    4798             : 
    4799             :   template <typename A = alloc_ty,
    4800             :             typename std::enable_if<allocations_are_swappable<A>::value
    4801             :                                     &&  InlineCapacity == 0>::type * = nullptr>
    4802             :   PLUMED_GCH_CPP20_CONSTEXPR
    4803             :   void
    4804             :   swap (small_vector_base& other) noexcept
    4805             :   {
    4806             :     swap_allocation (other);
    4807             :     alloc_interface::swap (other);
    4808             :   }
    4809             : 
    4810             :   template <typename A = alloc_ty,
    4811             :             typename std::enable_if<allocations_are_swappable<A>::value
    4812             :                                     &&  InlineCapacity != 0>::type * = nullptr>
    4813             :   PLUMED_GCH_CPP20_CONSTEXPR
    4814             :   void
    4815             :   swap (small_vector_base& other)
    4816             :   noexcept (std::is_nothrow_move_constructible<value_ty>::value
    4817             : #ifdef PLUMED_GCH_LIB_IS_SWAPPABLE
    4818             :             &&  std::is_nothrow_swappable<value_ty>::value
    4819             : #else
    4820             :             &&  detail::small_vector_adl::is_nothrow_swappable<value_ty>::value
    4821             : #endif
    4822             :                                          )
    4823             :   {
    4824             :     if (get_capacity () < other.get_capacity ())
    4825             :           swap_default (other);
    4826             :     else
    4827             :       other.swap_default (*this);
    4828             :   }
    4829             : 
    4830             :   template <typename A = alloc_ty,
    4831             :             typename std::enable_if<! allocations_are_swappable<A>::value>::type * = nullptr>
    4832             :   PLUMED_GCH_CPP20_CONSTEXPR
    4833             :   void
    4834             :   swap (small_vector_base& other)
    4835             :   {
    4836             :     if (get_capacity () < other.get_capacity ())
    4837             :     {
    4838             :       if (other.allocator_ref () == allocator_ref ())
    4839             :         swap_default (other);
    4840             :       else
    4841             :         swap_unequal_no_propagate (other);
    4842             :     }
    4843             :     else
    4844             :     {
    4845             :       if (other.allocator_ref () == allocator_ref ())
    4846             :         other.swap_default (*this);
    4847             :       else
    4848             :         other.swap_unequal_no_propagate (*this);
    4849             :     }
    4850             :   }
    4851             : 
    4852             : #ifdef __GLIBCXX__
    4853             : 
    4854             :   // These are compatibility fixes for libstdc++ because std::copy doesn't work for
    4855             :   // `move_iterator`s when constant evaluated.
    4856             : 
    4857             :   template <typename InputIt>
    4858             :   static PLUMED_GCH_CPP20_CONSTEXPR
    4859             :   InputIt
    4860             :   unmove_iterator (InputIt it)
    4861             :   {
    4862             :     return it;
    4863             :   }
    4864             : 
    4865             :   template <typename InputIt>
    4866             :   static PLUMED_GCH_CPP20_CONSTEXPR
    4867             :   auto
    4868             :   unmove_iterator (std::move_iterator<InputIt> it)
    4869             :   -> decltype (unmove_iterator (it.base ()))
    4870             :   {
    4871             :     return unmove_iterator (it.base ());
    4872             :   }
    4873             : 
    4874             :   template <typename InputIt>
    4875             :   static PLUMED_GCH_CPP20_CONSTEXPR
    4876             :   auto
    4877             :   unmove_iterator (std::reverse_iterator<InputIt> it)
    4878             :   -> std::reverse_iterator<decltype (unmove_iterator (it.base ()))>
    4879             :   {
    4880             :     return std::reverse_iterator<decltype (unmove_iterator (it.base ()))> (
    4881             :       unmove_iterator (it.base ()));
    4882             :                                 }
    4883             : 
    4884             : #endif
    4885             : 
    4886             :   template <typename InputIt>
    4887             :   PLUMED_GCH_CPP20_CONSTEXPR
    4888             :   ptr
    4889             :   copy_range (InputIt first, InputIt last, ptr dest)
    4890             :   {
    4891             : #if defined (PLUMED_GCH_LIB_IS_CONSTANT_EVALUATED) && defined (__GLIBCXX__)
    4892             :     if (    std::is_constant_evaluated ()
    4893             :             &&! std::is_same<decltype (unmove_iterator (std::declval<InputIt> ())),
    4894             :                              InputIt>::value)
    4895             :     {
    4896             :       return std::move (unmove_iterator (first), unmove_iterator (last), dest);
    4897             :     }
    4898             : #endif
    4899             : 
    4900             :     return std::copy (first, last, dest);
    4901             :   }
    4902             : 
    4903             :   template <typename InputIt,
    4904             :             typename std::enable_if<
    4905             :               is_memcpyable_iterator<InputIt>::value>::type * = nullptr>
    4906             :   PLUMED_GCH_CPP20_CONSTEXPR
    4907             :   InputIt
    4908             :   copy_n_return_in (InputIt first, size_ty count, ptr dest) noexcept
    4909             :   {
    4910             : #ifdef PLUMED_GCH_LIB_IS_CONSTANT_EVALUATED
    4911             :     if (std::is_constant_evaluated ())
    4912             :     {
    4913             :       std::copy_n (first, count, dest);
    4914             :       return unchecked_next (first, count);
    4915             :     }
    4916             : #endif
    4917             : 
    4918             :     if (count != 0)
    4919             :       std::memcpy (to_address (dest), to_address (first), count * sizeof (value_ty));
    4920             :     // Note: The unsafe cast here should be proven to be safe in the caller function.
    4921             :     return unchecked_next (first, count);
    4922             :   }
    4923             : 
    4924             :   template <typename InputIt,
    4925             :             typename std::enable_if<
    4926             :               is_memcpyable_iterator<InputIt>::value>::type * = nullptr>
    4927             :   PLUMED_GCH_CPP20_CONSTEXPR
    4928             :   std::move_iterator<InputIt>
    4929             :   copy_n_return_in (std::move_iterator<InputIt> first, size_ty count, ptr dest) noexcept
    4930             :   {
    4931             :     return std::move_iterator<InputIt> (copy_n_return_in (first.base (), count, dest));
    4932             :   }
    4933             : 
    4934             :   template <typename RandomIt,
    4935             :             typename std::enable_if<
    4936             :               ! is_memcpyable_iterator<RandomIt>::value
    4937             :               &&  std::is_base_of<std::random_access_iterator_tag,
    4938             :                                   typename std::iterator_traits<RandomIt>::iterator_category>::value
    4939             :               >::type * = nullptr>
    4940             :   PLUMED_GCH_CPP20_CONSTEXPR
    4941             :   RandomIt
    4942             :   copy_n_return_in (RandomIt first, size_ty count, ptr dest)
    4943             :   {
    4944             : #if defined (PLUMED_GCH_LIB_IS_CONSTANT_EVALUATED) && defined (__GLIBCXX__)
    4945             :     if (    std::is_constant_evaluated ()
    4946             :             &&! std::is_same<decltype (unmove_iterator (std::declval<RandomIt> ())),
    4947             :                              RandomIt>::value)
    4948             :     {
    4949             :       auto bfirst = unmove_iterator (first);
    4950             :       auto blast  = unchecked_next (bfirst, count);
    4951             :       std::move (bfirst, blast, dest);
    4952             :       return unchecked_next (first, count);
    4953             :     }
    4954             : #endif
    4955             : 
    4956             :     std::copy_n (first, count, dest);
    4957             :     // Note: This unsafe cast should be proven safe in the caller function.
    4958             :     return unchecked_next (first, count);
    4959             :   }
    4960             : 
    4961             :   template <typename InputIt,
    4962             :             typename std::enable_if<
    4963             :               ! is_memcpyable_iterator<InputIt>::value
    4964             :               &&! std::is_base_of<std::random_access_iterator_tag,
    4965             :                                   typename std::iterator_traits<InputIt>::iterator_category>::value
    4966             :               >::type * = nullptr>
    4967             :   PLUMED_GCH_CPP20_CONSTEXPR
    4968             :   InputIt
    4969             :   copy_n_return_in (InputIt first, size_ty count, ptr dest)
    4970             :   {
    4971             : 
    4972             :     for (; count != 0; --count, static_cast<void> (++dest), static_cast<void> (++first))
    4973             :       *dest = *first;
    4974             :     return first;
    4975             :   }
    4976             : 
    4977             :   template <typename V = value_ty,
    4978             :             typename std::enable_if<is_memcpyable<V>::value>::type * = nullptr>
    4979             :   PLUMED_GCH_CPP20_CONSTEXPR
    4980             :   ptr
    4981             :   move_left (ptr first, ptr last, ptr d_first)
    4982             :   {
    4983             :     // Shift initialized elements to the left.
    4984             : 
    4985             : #ifdef PLUMED_GCH_LIB_IS_CONSTANT_EVALUATED
    4986             :     if (std::is_constant_evaluated ())
    4987             :       return std::move (first, last, d_first);
    4988             : #endif
    4989             : 
    4990             :     const size_ty num_moved = internal_range_length (first, last);
    4991             :     if (num_moved != 0)
    4992             :       std::memmove (to_address (d_first), to_address (first), num_moved * sizeof (value_ty));
    4993             :     return unchecked_next (d_first, num_moved);
    4994             :   }
    4995             : 
    4996             :   template <typename V = value_ty,
    4997             :             typename std::enable_if<! is_memcpyable<V>::value>::type * = nullptr>
    4998             :   PLUMED_GCH_CPP20_CONSTEXPR
    4999             :   ptr
    5000             :   move_left (ptr first, ptr last, ptr d_first)
    5001             :   {
    5002             :     // Shift initialized elements to the left.
    5003             :     return std::move (first, last, d_first);
    5004             :   }
    5005             : 
    5006             :   template <typename V = value_ty,
    5007             :             typename std::enable_if<is_memcpyable<V>::value, bool>::type = true>
    5008             :   PLUMED_GCH_CPP20_CONSTEXPR
    5009             :   ptr
    5010             :   move_right (ptr first, ptr last, ptr d_last)
    5011             :   {
    5012             :     // Move initialized elements to the right.
    5013             : 
    5014             : #ifdef PLUMED_GCH_LIB_IS_CONSTANT_EVALUATED
    5015             :     if (std::is_constant_evaluated ())
    5016             :       return std::move_backward (first, last, d_last);
    5017             : #endif
    5018             : 
    5019             :     const size_ty num_moved = internal_range_length (first, last);
    5020             :     const ptr     dest      = unchecked_prev (d_last, num_moved);
    5021             :     if (num_moved != 0)
    5022             :       std::memmove (to_address (dest), to_address (first), num_moved * sizeof (value_ty));
    5023             :     return dest;
    5024             :   }
    5025             : 
    5026             :   template <typename V = value_ty,
    5027             :             typename std::enable_if<! is_memcpyable<V>::value, bool>::type = false>
    5028             :   PLUMED_GCH_CPP20_CONSTEXPR
    5029             :   ptr
    5030             :   move_right (ptr first, ptr last, ptr d_last)
    5031             :   {
    5032             :     // move initialized elements to the right
    5033             :     // n should not be 0
    5034             :     return std::move_backward (first, last, d_last);
    5035             :   }
    5036             : 
    5037             : public:
    5038             :   PLUMED_GCH_CPP20_CONSTEXPR
    5039             :   void
    5040             :   set_default (void)
    5041             :   {
    5042             :     set_to_inline_storage ();
    5043             :     set_size (0);
    5044             :   }
    5045             : 
    5046             :   PLUMED_GCH_NODISCARD PLUMED_GCH_CPP14_CONSTEXPR
    5047             :   ptr
    5048             :   data_ptr (void) noexcept
    5049             :   {
    5050             :     return m_data.data_ptr ();
    5051             :   }
    5052             : 
    5053             :   PLUMED_GCH_NODISCARD constexpr
    5054             :   cptr
    5055             :   data_ptr (void) const noexcept
    5056             :   {
    5057             :     return m_data.data_ptr ();
    5058             :   }
    5059             : 
    5060             :   PLUMED_GCH_NODISCARD constexpr
    5061             :   size_ty
    5062             :   get_capacity (void) const noexcept
    5063             :   {
    5064             :     return m_data.capacity ();
    5065             :   }
    5066             : 
    5067             :   PLUMED_GCH_NODISCARD constexpr
    5068             :   size_ty
    5069             :   get_size (void) const noexcept
    5070             :   {
    5071             :     return m_data.size ();
    5072             :   }
    5073             : 
    5074             :   PLUMED_GCH_NODISCARD constexpr
    5075             :   size_ty
    5076             :   num_uninitialized (void) const noexcept
    5077             :   {
    5078             :     return get_capacity () - get_size ();
    5079             :   }
    5080             : 
    5081             :   PLUMED_GCH_NODISCARD PLUMED_GCH_CPP14_CONSTEXPR
    5082             :   ptr
    5083             :   begin_ptr (void) noexcept
    5084             :   {
    5085             :     return data_ptr ();
    5086             :   }
    5087             : 
    5088             :   PLUMED_GCH_NODISCARD
    5089             :   constexpr
    5090             :   cptr
    5091             :   begin_ptr (void) const noexcept
    5092             :   {
    5093             :     return data_ptr ();
    5094             :   }
    5095             : 
    5096             :   PLUMED_GCH_NODISCARD PLUMED_GCH_CPP14_CONSTEXPR
    5097             :   ptr
    5098    16733731 :   end_ptr (void) noexcept
    5099             :   {
    5100    16733731 :     return unchecked_next (begin_ptr (), get_size ());
    5101             :   }
    5102             : 
    5103             :   PLUMED_GCH_NODISCARD constexpr
    5104             :   cptr
    5105     4208848 :   end_ptr (void) const noexcept
    5106             :   {
    5107     4208848 :     return unchecked_next (begin_ptr (), get_size ());
    5108             :   }
    5109             : 
    5110             :   PLUMED_GCH_NODISCARD PLUMED_GCH_CPP14_CONSTEXPR
    5111             :   ptr
    5112        1313 :   allocation_end_ptr (void) noexcept
    5113             :   {
    5114        1313 :     return unchecked_next (begin_ptr (), get_capacity ());
    5115             :   }
    5116             : 
    5117             :   PLUMED_GCH_NODISCARD constexpr
    5118             :   cptr
    5119           0 :   allocation_end_ptr (void) const noexcept
    5120             :   {
    5121           0 :     return unchecked_next (begin_ptr (), get_capacity ());
    5122             :   }
    5123             : 
    5124             :   PLUMED_GCH_NODISCARD constexpr
    5125             :   alloc_ty
    5126             :   copy_allocator (void) const noexcept
    5127             :   {
    5128             :     return alloc_ty (allocator_ref ());
    5129             :   }
    5130             : 
    5131             :   PLUMED_GCH_NODISCARD PLUMED_GCH_CPP14_CONSTEXPR
    5132             :   ptr
    5133             :   storage_ptr (void) noexcept
    5134             :   {
    5135             :     return m_data.storage ();
    5136             :   }
    5137             : 
    5138             :   PLUMED_GCH_NODISCARD constexpr
    5139             :   cptr
    5140             :   storage_ptr (void) const noexcept
    5141             :   {
    5142             :     return m_data.storage ();
    5143             :   }
    5144             : 
    5145             :   PLUMED_GCH_NODISCARD constexpr
    5146             :   bool
    5147             :   has_allocation (void) const noexcept
    5148             :   {
    5149             : #ifdef PLUMED_GCH_LIB_IS_CONSTANT_EVALUATED
    5150             :     if (std::is_constant_evaluated ())
    5151             :       return true;
    5152             : #endif
    5153             :     return InlineCapacity < get_capacity ();
    5154             :   }
    5155             : 
    5156             :   PLUMED_GCH_NODISCARD constexpr
    5157             :   bool
    5158             :   is_inlinable (void) const noexcept
    5159             :   {
    5160             :     return get_size () <= InlineCapacity;
    5161             :   }
    5162             : 
    5163             : private:
    5164             :   small_vector_data<ptr, size_type, value_ty, InlineCapacity> m_data;
    5165             : };
    5166             : 
    5167             : } // namespace gch::detail
    5168             : 
    5169             : template <typename T, unsigned InlineCapacity, typename Allocator>
    5170             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5171             : requires concepts::small_vector::AllocatorFor<Allocator, T>
    5172             : #endif
    5173             : class small_vector
    5174             : : private detail::small_vector_base<Allocator, InlineCapacity>
    5175             : {
    5176             :   using base = detail::small_vector_base<Allocator, InlineCapacity>;
    5177             : 
    5178             : public:
    5179             :   static_assert (std::is_same<T, typename Allocator::value_type>::value,
    5180             :                  "`Allocator::value_type` must be the same as `T`.");
    5181             : 
    5182             :   template <typename SameT, unsigned DifferentInlineCapacity, typename SameAllocator>
    5183             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5184             :   requires concepts::small_vector::AllocatorFor<SameAllocator, SameT>
    5185             : #endif
    5186             :   friend class small_vector;
    5187             : 
    5188             :   using value_type             = T;
    5189             :   using allocator_type         = Allocator;
    5190             :   using size_type              = typename base::size_type;
    5191             :   using difference_type        = typename base::difference_type;
    5192             :   using reference              =       value_type&;
    5193             :   using const_reference        = const value_type&;
    5194             :   using pointer                = typename std::allocator_traits<allocator_type>::pointer;
    5195             :   using const_pointer          = typename std::allocator_traits<allocator_type>::const_pointer;
    5196             : 
    5197             :   using iterator               = small_vector_iterator<pointer, difference_type>;
    5198             :   using const_iterator         = small_vector_iterator<const_pointer, difference_type>;
    5199             :   using reverse_iterator       = std::reverse_iterator<iterator>;
    5200             :   using const_reverse_iterator = std::reverse_iterator<const_iterator>;
    5201             : 
    5202             :   static_assert (InlineCapacity <= (std::numeric_limits<size_type>::max) (),
    5203             :                  "InlineCapacity must be less than or equal to the maximum value of size_type.");
    5204             : 
    5205             :   static constexpr
    5206             :   unsigned
    5207             :   inline_capacity_v = InlineCapacity;
    5208             : 
    5209             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5210             : 
    5211             : private:
    5212             :   static constexpr
    5213             :   bool
    5214             :   Destructible = concepts::small_vector::Destructible<value_type>;
    5215             : 
    5216             :   static constexpr
    5217             :   bool
    5218             :   MoveAssignable = concepts::small_vector::MoveAssignable<value_type>;
    5219             : 
    5220             :   static constexpr
    5221             :   bool
    5222             :   CopyAssignable = concepts::small_vector::CopyAssignable<value_type>;
    5223             : 
    5224             :   static constexpr
    5225             :   bool
    5226             :   MoveConstructible = concepts::small_vector::MoveConstructible<value_type>;
    5227             : 
    5228             :   static constexpr
    5229             :   bool
    5230             :   CopyConstructible = concepts::small_vector::CopyConstructible<value_type>;
    5231             : 
    5232             :   static constexpr
    5233             :   bool
    5234             :   Swappable = concepts::small_vector::Swappable<value_type>;
    5235             : 
    5236             :   static constexpr
    5237             :   bool
    5238             :   DefaultInsertable = concepts::small_vector::DefaultInsertable<value_type, small_vector,
    5239             :   allocator_type>;
    5240             : 
    5241             :   static constexpr
    5242             :   bool
    5243             :   MoveInsertable = concepts::small_vector::MoveInsertable<value_type, small_vector,
    5244             :   allocator_type>;
    5245             : 
    5246             :   static constexpr
    5247             :   bool
    5248             :   CopyInsertable = concepts::small_vector::CopyInsertable<value_type, small_vector,
    5249             :   allocator_type>;
    5250             : 
    5251             :   static constexpr
    5252             :   bool
    5253             :   Erasable = concepts::small_vector::Erasable<value_type, small_vector, allocator_type>;
    5254             : 
    5255             :   template <typename ...Args>
    5256             :   struct EmplaceConstructible
    5257             :   {
    5258             :     static constexpr
    5259             :     bool
    5260             :     value = concepts::small_vector::EmplaceConstructible<value_type, small_vector,
    5261             :         allocator_type, Args...>;
    5262             :                                                         };
    5263             : 
    5264             : public:
    5265             : 
    5266             : #endif
    5267             : 
    5268             :   PLUMED_GCH_CPP20_CONSTEXPR
    5269             :   small_vector (void)
    5270             :   noexcept (noexcept (allocator_type ()))
    5271             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5272             :   requires concepts::DefaultConstructible<allocator_type>
    5273             : #endif
    5274             :     = default;
    5275             : 
    5276             :   PLUMED_GCH_CPP20_CONSTEXPR
    5277             :   small_vector (const small_vector& other)
    5278             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5279             :   requires CopyInsertable
    5280             : #endif
    5281             : : base (base::bypass, other)
    5282             :   { }
    5283             : 
    5284             :   PLUMED_GCH_CPP20_CONSTEXPR
    5285             :   small_vector (small_vector&& other)
    5286             :   noexcept (std::is_nothrow_move_constructible<value_type>::value || InlineCapacity == 0)
    5287             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5288             :   requires MoveInsertable
    5289             : #endif
    5290             : : base (base::bypass, std::move (other))
    5291             :   { }
    5292             : 
    5293             :   PLUMED_GCH_CPP20_CONSTEXPR explicit
    5294             :   small_vector (const allocator_type& alloc) noexcept
    5295             :     : base (alloc)
    5296             :   { }
    5297             : 
    5298             :   PLUMED_GCH_CPP20_CONSTEXPR
    5299             :   small_vector (const small_vector& other, const allocator_type& alloc)
    5300             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5301             :   requires CopyInsertable
    5302             : #endif
    5303             : : base (base::bypass, other, alloc)
    5304             :   { }
    5305             : 
    5306             :   PLUMED_GCH_CPP20_CONSTEXPR
    5307             :   small_vector (small_vector&& other, const allocator_type& alloc)
    5308             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5309             :   requires MoveInsertable
    5310             : #endif
    5311             : : base (base::bypass, std::move (other), alloc)
    5312             :   { }
    5313             : 
    5314             :   PLUMED_GCH_CPP20_CONSTEXPR explicit
    5315        3738 :   small_vector (size_type count, const allocator_type& alloc = allocator_type ())
    5316             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5317             :   requires DefaultInsertable
    5318             : #endif
    5319        3738 : : base (count, alloc)
    5320             :   { }
    5321             : 
    5322             :   PLUMED_GCH_CPP20_CONSTEXPR
    5323             :   small_vector (size_type count, const_reference value,
    5324             :                 const allocator_type& alloc = allocator_type ())
    5325             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5326             :   requires CopyInsertable
    5327             : #endif
    5328             : : base (count, value, alloc)
    5329             :   { }
    5330             : 
    5331             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5332             :   template <typename Generator>
    5333             :   requires std::invocable<Generator&>
    5334             :   &&  EmplaceConstructible<std::invoke_result_t<Generator&>>::value
    5335             : #else
    5336             :   template <typename Generator,
    5337             :             typename std::enable_if<
    5338             :               ! std::is_convertible<Generator, const_reference>::value>::type * = nullptr>
    5339             : #endif
    5340             :   PLUMED_GCH_CPP20_CONSTEXPR
    5341             :   small_vector (size_type count, Generator g, const allocator_type& alloc = allocator_type ())
    5342             :     : base (count, g, alloc)
    5343             :   { }
    5344             : 
    5345             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5346             :   template <std::input_iterator InputIt>
    5347             :   requires EmplaceConstructible<std::iter_reference_t<InputIt>>::value
    5348             :   &&  (std::forward_iterator<InputIt> || MoveInsertable)
    5349             : #else
    5350             :   template <typename InputIt,
    5351             :             typename std::enable_if<
    5352             :               std::is_base_of<
    5353             :                 std::input_iterator_tag,
    5354             :                 typename std::iterator_traits<InputIt>::iterator_category>::value
    5355             :               >::type * = nullptr>
    5356             : #endif
    5357             :   PLUMED_GCH_CPP20_CONSTEXPR
    5358             :   small_vector (InputIt first, InputIt last, const allocator_type& alloc = allocator_type ())
    5359             :     : base (first, last, typename std::iterator_traits<InputIt>::iterator_category { }, alloc)
    5360             :   { }
    5361             : 
    5362             :   PLUMED_GCH_CPP20_CONSTEXPR
    5363             :   small_vector (std::initializer_list<value_type> init,
    5364             :                 const allocator_type& alloc = allocator_type ())
    5365             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5366             :   requires EmplaceConstructible<const_reference>::value
    5367             : #endif
    5368             : : small_vector (init.begin (), init.end (), alloc)
    5369             :   { }
    5370             : 
    5371             :   template <unsigned I>
    5372             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5373             :   requires CopyInsertable
    5374             : #endif
    5375             :   PLUMED_GCH_CPP20_CONSTEXPR explicit
    5376             :   small_vector (const small_vector<T, I, Allocator>& other)
    5377             :     : base (base::bypass, other)
    5378             :   { }
    5379             : 
    5380             :   template <unsigned I>
    5381             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5382             :   requires MoveInsertable
    5383             : #endif
    5384             :   PLUMED_GCH_CPP20_CONSTEXPR explicit
    5385             :   small_vector (small_vector<T, I, Allocator>&& other)
    5386             :   noexcept (std::is_nothrow_move_constructible<value_type>::value && I < InlineCapacity)
    5387             :               : base (base::bypass, std::move (other))
    5388             :   { }
    5389             : 
    5390             :   template <unsigned I>
    5391             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5392             :   requires CopyInsertable
    5393             : #endif
    5394             :   PLUMED_GCH_CPP20_CONSTEXPR
    5395             :   small_vector (const small_vector<T, I, Allocator>& other, const allocator_type& alloc)
    5396             :     : base (base::bypass, other, alloc)
    5397             :   { }
    5398             : 
    5399             :   template <unsigned I>
    5400             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5401             :   requires MoveInsertable
    5402             : #endif
    5403             :   PLUMED_GCH_CPP20_CONSTEXPR
    5404             :   small_vector (small_vector<T, I, Allocator>&& other, const allocator_type& alloc)
    5405             :     : base (base::bypass, std::move (other), alloc)
    5406             :   { }
    5407             : 
    5408             :   PLUMED_GCH_CPP20_CONSTEXPR
    5409     1428222 :   ~small_vector (void)
    5410             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5411             :   requires Erasable
    5412             : #endif
    5413             :     = default;
    5414             : 
    5415             :   PLUMED_GCH_CPP20_CONSTEXPR
    5416             :   small_vector&
    5417             :   operator= (const small_vector& other)
    5418             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5419             :   requires CopyInsertable && CopyAssignable
    5420             : #endif
    5421             :   {
    5422             :     assign (other);
    5423             :     return *this;
    5424             :   }
    5425             : 
    5426             :   PLUMED_GCH_CPP20_CONSTEXPR
    5427             :   small_vector&
    5428             :   operator= (small_vector&& other)
    5429             :   noexcept (  (  std::is_same<std::allocator<value_type>, Allocator>::value
    5430             :                  ||  std::allocator_traits<Allocator>::propagate_on_container_move_assignment::value
    5431             : #ifdef PLUMED_GCH_LIB_IS_ALWAYS_EQUAL
    5432             :                  ||  std::allocator_traits<Allocator>::is_always_equal::value
    5433             : #endif
    5434             :               )
    5435             :               &&  (  (  std::is_nothrow_move_assignable<value_type>::value
    5436             :                         &&  std::is_nothrow_move_constructible<value_type>::value
    5437             :                      )
    5438             :                      ||  InlineCapacity == 0
    5439             :                   )
    5440             :            )
    5441             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5442             :   // Note: The standard says here that
    5443             :   // std::allocator_traits<allocator_type>::propagate_on_container_move_assignment == false
    5444             :   // implies MoveInsertable && MoveAssignable, but since we have inline storage we must always
    5445             :   // require moves [tab:container.alloc.req].
    5446             :   requires MoveInsertable && MoveAssignable
    5447             : #endif
    5448             :   {
    5449             :     assign (std::move (other));
    5450             :     return *this;
    5451             :   }
    5452             : 
    5453             :   PLUMED_GCH_CPP20_CONSTEXPR
    5454             :   small_vector&
    5455             :   operator= (std::initializer_list<value_type> ilist)
    5456             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5457             :   requires CopyInsertable && CopyAssignable
    5458             : #endif
    5459             :   {
    5460             :     assign (ilist);
    5461             :     return *this;
    5462             :   }
    5463             : 
    5464             :   PLUMED_GCH_CPP20_CONSTEXPR
    5465             :   void
    5466             :   assign (size_type count, const_reference value)
    5467             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5468             :   requires CopyInsertable && CopyAssignable
    5469             : #endif
    5470             :   {
    5471             :     base::assign_with_copies (count, value);
    5472             :   }
    5473             : 
    5474             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5475             :   template <std::input_iterator InputIt>
    5476             :   requires EmplaceConstructible<std::iter_reference_t<InputIt>>::value
    5477             :   &&  (std::forward_iterator<InputIt> || MoveInsertable)
    5478             : #else
    5479             :   template <typename InputIt,
    5480             :             typename std::enable_if<std::is_base_of<
    5481             :                                       std::input_iterator_tag,
    5482             :                                       typename std::iterator_traits<InputIt>::iterator_category
    5483             :                                       >::value>::type * = nullptr>
    5484             : #endif
    5485             :   PLUMED_GCH_CPP20_CONSTEXPR
    5486             :   void
    5487             :   assign (InputIt first, InputIt last)
    5488             :   {
    5489             :     using iterator_cat = typename std::iterator_traits<InputIt>::iterator_category;
    5490             :     base::assign_with_range (first, last, iterator_cat { });
    5491             :   }
    5492             : 
    5493             :   PLUMED_GCH_CPP20_CONSTEXPR
    5494             :   void
    5495             :   assign (std::initializer_list<value_type> ilist)
    5496             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5497             :   requires EmplaceConstructible<const_reference>::value
    5498             : #endif
    5499             :   {
    5500             :     assign (ilist.begin (), ilist.end ());
    5501             :   }
    5502             : 
    5503             :   PLUMED_GCH_CPP20_CONSTEXPR
    5504             :   void
    5505             :   assign (const small_vector& other)
    5506             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5507             :   requires CopyInsertable && CopyAssignable
    5508             : #endif
    5509             :   {
    5510             :     if (&other != this)
    5511             :       base::copy_assign (other);
    5512             :   }
    5513             : 
    5514             :   template <unsigned I>
    5515             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5516             :   requires CopyInsertable && CopyAssignable
    5517             : #endif
    5518             :   PLUMED_GCH_CPP20_CONSTEXPR
    5519             :   void
    5520             :   assign (const small_vector<T, I, Allocator>& other)
    5521             :   {
    5522             :     base::copy_assign (other);
    5523             :   }
    5524             : 
    5525             :   PLUMED_GCH_CPP20_CONSTEXPR
    5526             :   void
    5527             :   assign (small_vector&& other)
    5528             :   noexcept (  (  std::is_same<std::allocator<value_type>, Allocator>::value
    5529             :                  ||  std::allocator_traits<Allocator>::propagate_on_container_move_assignment::value
    5530             : #ifdef PLUMED_GCH_LIB_IS_ALWAYS_EQUAL
    5531             :                  ||  std::allocator_traits<Allocator>::is_always_equal::value
    5532             : #endif
    5533             :               )
    5534             :               &&  (  (  std::is_nothrow_move_assignable<value_type>::value
    5535             :                         &&  std::is_nothrow_move_constructible<value_type>::value
    5536             :                      )
    5537             :                      ||  InlineCapacity == 0
    5538             :                   )
    5539             :            )
    5540             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5541             :   requires MoveInsertable && MoveAssignable
    5542             : #endif
    5543             :   {
    5544             :     if (&other != this)
    5545             :       base::move_assign (std::move (other));
    5546             :   }
    5547             : 
    5548             :   template <unsigned I>
    5549             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5550             :   requires MoveInsertable && MoveAssignable
    5551             : #endif
    5552             :   PLUMED_GCH_CPP20_CONSTEXPR
    5553             :   void
    5554             :   assign (small_vector<T, I, Allocator>&& other)
    5555             :   noexcept (  I <= InlineCapacity
    5556             :                  &&  (  std::is_same<std::allocator<value_type>, Allocator>::value
    5557             :                         ||  std::allocator_traits<Allocator>::propagate_on_container_move_assignment::value
    5558             : #ifdef PLUMED_GCH_LIB_IS_ALWAYS_EQUAL
    5559             :                         ||  std::allocator_traits<Allocator>::is_always_equal::value
    5560             : #endif
    5561             :                                                  )
    5562             :                  &&  std::is_nothrow_move_assignable<value_type>::value
    5563             :                  &&  std::is_nothrow_move_constructible<value_type>::value
    5564             :                                                        )
    5565             :   {
    5566             :     base::move_assign (std::move (other));
    5567             :   }
    5568             : 
    5569             : #ifndef PLUMED_GCH_LIB_CONCEPTS
    5570             :   template <typename ValueType = value_type,
    5571             :             typename std::enable_if<
    5572             :               (  std::is_move_constructible<ValueType>::value
    5573             :                  &&  std::is_move_assignable<ValueType>::value
    5574             : #ifdef PLUMED_GCH_LIB_IS_SWAPPABLE
    5575             :                  &&  std::is_swappable<ValueType>::value
    5576             : #endif
    5577             :                                       )
    5578             :               ||  (  (  std::is_same<std::allocator<value_type>, Allocator>::value
    5579             :                         ||  std::allocator_traits<Allocator>::propagate_on_container_swap::value
    5580             : #ifdef PLUMED_GCH_LIB_IS_ALWAYS_EQUAL
    5581             :                         ||  std::allocator_traits<Allocator>::is_always_equal::value
    5582             : #endif
    5583             :                                                  )
    5584             :                      &&  InlineCapacity == 0
    5585             :                                                  )
    5586             :               >::type * = nullptr>
    5587             : #endif
    5588             :   PLUMED_GCH_CPP20_CONSTEXPR
    5589             :   void
    5590             :   swap (small_vector& other)
    5591             :   noexcept (  (  std::is_same<std::allocator<value_type>, Allocator>::value
    5592             :                  ||  std::allocator_traits<Allocator>::propagate_on_container_swap::value
    5593             : #ifdef PLUMED_GCH_LIB_IS_ALWAYS_EQUAL
    5594             :                  ||  std::allocator_traits<Allocator>::is_always_equal::value
    5595             : #endif
    5596             :                                           )
    5597             :               &&  (  (  std::is_nothrow_move_constructible<value_type>::value
    5598             :                         &&  std::is_nothrow_move_assignable<value_type>::value
    5599             : #ifdef PLUMED_GCH_LIB_IS_SWAPPABLE
    5600             :                         &&  std::is_nothrow_swappable<value_type>::value
    5601             : #else
    5602             :                         &&  detail::small_vector_adl::is_nothrow_swappable<value_type>::value
    5603             : #endif
    5604             :                                                      )
    5605             :                      ||  InlineCapacity == 0
    5606             :                                                            )
    5607             :                                                           )
    5608             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5609             :   requires (MoveInsertable && MoveAssignable && Swappable)
    5610             :   ||  (  (  std::is_same<std::allocator<value_type>, Allocator>::value
    5611             :             ||  std::allocator_traits<Allocator>::propagate_on_container_swap::value
    5612             : #ifdef PLUMED_GCH_LIB_IS_ALWAYS_EQUAL
    5613             :             ||  std::allocator_traits<Allocator>::is_always_equal::value
    5614             : #endif
    5615             :                                      )
    5616             :          &&  InlineCapacity == 0
    5617             :                                      )
    5618             : #endif
    5619             :   {
    5620             :     base::swap (other);
    5621             :   }
    5622             : 
    5623             :   PLUMED_GCH_CPP14_CONSTEXPR
    5624             :   iterator
    5625             :   begin (void) noexcept
    5626             :   {
    5627             :     return iterator { base::begin_ptr () };
    5628             :   }
    5629             : 
    5630             :   constexpr
    5631             :   const_iterator
    5632             :   begin (void) const noexcept
    5633             :   {
    5634             :     return const_iterator { base::begin_ptr () };
    5635             :   }
    5636             : 
    5637             :   constexpr
    5638             :   const_iterator
    5639             :   cbegin (void) const noexcept
    5640             :   {
    5641             :     return begin ();
    5642             :   }
    5643             : 
    5644             :   PLUMED_GCH_CPP14_CONSTEXPR
    5645             :   iterator
    5646             :   end (void) noexcept
    5647             :   {
    5648     4957660 :     return iterator { base::end_ptr () };
    5649             :   }
    5650             : 
    5651             :   constexpr
    5652             :   const_iterator
    5653             :   end (void) const noexcept
    5654             :   {
    5655             :     return const_iterator { base::end_ptr () };
    5656             :   }
    5657             : 
    5658             :   constexpr
    5659             :   const_iterator
    5660             :   cend (void) const noexcept
    5661             :   {
    5662             :     return end ();
    5663             :   }
    5664             : 
    5665             :   PLUMED_GCH_CPP14_CONSTEXPR
    5666             :   reverse_iterator
    5667             :   rbegin (void) noexcept
    5668             :   {
    5669             :     return reverse_iterator { end () };
    5670             :   }
    5671             : 
    5672             :   constexpr
    5673             :   const_reverse_iterator
    5674             :   rbegin (void) const noexcept
    5675             :   {
    5676             :     return const_reverse_iterator { end () };
    5677             :   }
    5678             : 
    5679             :   constexpr
    5680             :   const_reverse_iterator
    5681             :   crbegin (void) const noexcept
    5682             :   {
    5683             :     return rbegin ();
    5684             :   }
    5685             : 
    5686             :   PLUMED_GCH_CPP14_CONSTEXPR
    5687             :   reverse_iterator
    5688             :   rend (void) noexcept
    5689             :   {
    5690             :     return reverse_iterator { begin () };
    5691             :   }
    5692             : 
    5693             :   constexpr
    5694             :   const_reverse_iterator
    5695             :   rend (void) const noexcept
    5696             :   {
    5697             :     return const_reverse_iterator { begin () };
    5698             :   }
    5699             : 
    5700             :   constexpr
    5701             :   const_reverse_iterator
    5702             :   crend (void) const noexcept
    5703             :   {
    5704             :     return rend ();
    5705             :   }
    5706             : 
    5707             :   PLUMED_GCH_CPP14_CONSTEXPR
    5708             :   reference
    5709             :   at (size_type pos)
    5710             :   {
    5711             :     if (size () <= pos)
    5712             :       base::throw_index_error ();
    5713             :     return begin ()[static_cast<difference_type> (pos)];
    5714             :   }
    5715             : 
    5716             :   PLUMED_GCH_CPP14_CONSTEXPR
    5717             :   const_reference
    5718             :   at (size_type pos) const
    5719             :   {
    5720             :     if (size () <= pos)
    5721             :       base::throw_index_error ();
    5722             :     return begin ()[static_cast<difference_type> (pos)];
    5723             :   }
    5724             : 
    5725             :   PLUMED_GCH_CPP14_CONSTEXPR
    5726             :   reference
    5727             :   operator[] (size_type pos)
    5728             :   {
    5729             : #ifdef _GLIBCXX_DEBUG
    5730             :     if (size () <= pos) base::throw_index_error ();
    5731             : #endif
    5732             :     return begin ()[static_cast<difference_type> (pos)];
    5733             :   }
    5734             : 
    5735             :   constexpr
    5736             :   const_reference
    5737             :   operator[] (size_type pos) const
    5738             :   {
    5739             : #ifdef _GLIBCXX_DEBUG
    5740             :     if (size () <= pos) base::throw_index_error ();
    5741             : #endif
    5742             :     return begin ()[static_cast<difference_type> (pos)];
    5743             :   }
    5744             : 
    5745             :   PLUMED_GCH_CPP14_CONSTEXPR
    5746             :   reference
    5747             :   front (void)
    5748             :   {
    5749             :     return (*this)[0];
    5750             :   }
    5751             : 
    5752             :   constexpr
    5753             :   const_reference
    5754             :   front (void) const
    5755             :   {
    5756             :     return (*this)[0];
    5757             :   }
    5758             : 
    5759             :   PLUMED_GCH_CPP14_CONSTEXPR
    5760             :   reference
    5761             :   back (void)
    5762             :   {
    5763     2523923 :     return (*this)[size () - 1];
    5764             :   }
    5765             : 
    5766             :   constexpr
    5767             :   const_reference
    5768             :   back (void) const
    5769             :   {
    5770             :     return (*this)[size () - 1];
    5771             :   }
    5772             : 
    5773             :   PLUMED_GCH_CPP14_CONSTEXPR
    5774             :   pointer
    5775             :   data (void) noexcept
    5776             :   {
    5777             :     return base::begin_ptr ();
    5778             :   }
    5779             : 
    5780             :   constexpr
    5781             :   const_pointer
    5782             :   data (void) const noexcept
    5783             :   {
    5784             :     return base::begin_ptr ();
    5785             :   }
    5786             : 
    5787             :   constexpr
    5788             :   size_type
    5789             :   size (void) const noexcept
    5790             :   {
    5791             :     return static_cast<size_type> (base::get_size ());
    5792             :   }
    5793             : 
    5794             :   PLUMED_GCH_NODISCARD constexpr
    5795             :   bool
    5796             :   empty (void) const noexcept
    5797             :   {
    5798             :     return size () == 0;
    5799             :   }
    5800             : 
    5801             :   PLUMED_GCH_CPP14_CONSTEXPR
    5802             :   size_type
    5803             :   max_size (void) const noexcept
    5804             :   {
    5805             :     return static_cast<size_type> (base::get_max_size ());
    5806             :   }
    5807             : 
    5808             :   constexpr
    5809             :   size_type
    5810             :   capacity (void) const noexcept
    5811             :   {
    5812             :     return static_cast<size_type> (base::get_capacity ());
    5813             :   }
    5814             : 
    5815             :   constexpr
    5816             :   allocator_type
    5817             :   get_allocator (void) const noexcept
    5818             :   {
    5819             :     return base::copy_allocator ();
    5820             :   }
    5821             : 
    5822             :   PLUMED_GCH_CPP20_CONSTEXPR
    5823             :   iterator
    5824             :   insert (const_iterator pos, const_reference value)
    5825             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5826             :   requires CopyInsertable && CopyAssignable
    5827             : #endif
    5828             :   {
    5829             :     return emplace (pos, value);
    5830             :   }
    5831             : 
    5832             :   PLUMED_GCH_CPP20_CONSTEXPR
    5833             :   iterator
    5834             :   insert (const_iterator pos, value_type&& value)
    5835             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5836             :   requires MoveInsertable && MoveAssignable
    5837             : #endif
    5838             :   {
    5839             :     return emplace (pos, std::move (value));
    5840             :   }
    5841             : 
    5842             :   PLUMED_GCH_CPP20_CONSTEXPR
    5843             :   iterator
    5844             :   insert (const_iterator pos, size_type count, const_reference value)
    5845             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5846             :   requires CopyInsertable && CopyAssignable
    5847             : #endif
    5848             :   {
    5849             :     return iterator (base::insert_copies (base::ptr_cast (pos), count, value));
    5850             :   }
    5851             : 
    5852             :   // Note: Unlike std::vector, this does not require MoveConstructible because we
    5853             :   //       don't use std::rotate (as was the reason for the change in C++17).
    5854             :   //       Relevant: https://cplusplus.github.io/LWG/issue2266).
    5855             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5856             :   template <std::input_iterator InputIt>
    5857             :   requires EmplaceConstructible<std::iter_reference_t<InputIt>>::value
    5858             :   &&  MoveInsertable
    5859             :   &&  MoveAssignable
    5860             : #else
    5861             :   template <typename InputIt,
    5862             :             typename std::enable_if<std::is_base_of<
    5863             :                                       std::input_iterator_tag,
    5864             :                                       typename std::iterator_traits<InputIt>::iterator_category
    5865             :                                       >::value>::type * = nullptr>
    5866             : #endif
    5867             :   PLUMED_GCH_CPP20_CONSTEXPR
    5868             :   iterator
    5869             :   insert (const_iterator pos, InputIt first, InputIt last)
    5870             :   {
    5871             :     if (first == last)
    5872             :       return iterator (base::ptr_cast (pos));
    5873             : 
    5874             :     using iterator_cat = typename std::iterator_traits<InputIt>::iterator_category;
    5875             :     return iterator (base::insert_range (base::ptr_cast (pos), first, last, iterator_cat { }));
    5876             :   }
    5877             : 
    5878             :   PLUMED_GCH_CPP20_CONSTEXPR
    5879             :   iterator
    5880             :   insert (const_iterator pos, std::initializer_list<value_type> ilist)
    5881             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5882             :   requires EmplaceConstructible<const_reference>::value
    5883             :   &&  MoveInsertable
    5884             :   &&  MoveAssignable
    5885             : #endif
    5886             :   {
    5887             :     return insert (pos, ilist.begin (), ilist.end ());
    5888             :   }
    5889             : 
    5890             :   template <typename ...Args>
    5891             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5892             :   requires EmplaceConstructible<Args...>::value
    5893             :   &&  MoveInsertable
    5894             :   &&  MoveAssignable
    5895             : #endif
    5896             :   PLUMED_GCH_CPP20_CONSTEXPR
    5897             :   iterator
    5898             :   emplace (const_iterator pos, Args&&... args)
    5899             :   {
    5900             :     return iterator (base::emplace_at (base::ptr_cast (pos), std::forward<Args> (args)...));
    5901             :   }
    5902             : 
    5903             :   PLUMED_GCH_CPP20_CONSTEXPR
    5904             :   iterator
    5905             :   erase (const_iterator pos)
    5906             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5907             :   requires MoveAssignable && Erasable
    5908             : #endif
    5909             :   {
    5910             :     assert (0 <= (pos    - begin ()) && "`pos` is out of bounds (before `begin ()`)."   );
    5911             :     assert (0 <  (end () - pos)      && "`pos` is out of bounds (at or after `end ()`).");
    5912             : 
    5913             :     return iterator (base::erase_at (base::ptr_cast (pos)));
    5914             :   }
    5915             : 
    5916             :   PLUMED_GCH_CPP20_CONSTEXPR
    5917             :   iterator
    5918             :   erase (const_iterator first, const_iterator last)
    5919             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5920             :   requires MoveAssignable && Erasable
    5921             : #endif
    5922             :   {
    5923             :     assert (0 <= (last   - first)    && "Invalid range.");
    5924             :     assert (0 <= (first  - begin ()) && "`first` is out of bounds (before `begin ()`)."  );
    5925             :     assert (0 <= (end () - last)     && "`last` is out of bounds (after `end ()`).");
    5926             : 
    5927             :     return iterator (base::erase_range (base::ptr_cast (first), base::ptr_cast (last)));
    5928             :   }
    5929             : 
    5930             :   PLUMED_GCH_CPP20_CONSTEXPR
    5931             :   void
    5932             :   push_back (const_reference value)
    5933             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5934             :   requires CopyInsertable
    5935             : #endif
    5936             :   {
    5937             :     emplace_back (value);
    5938             :   }
    5939             : 
    5940             :   PLUMED_GCH_CPP20_CONSTEXPR
    5941             :   void
    5942             :   push_back (value_type&& value)
    5943             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5944             :   requires MoveInsertable
    5945             : #endif
    5946             :   {
    5947             :     emplace_back (std::move (value));
    5948      142050 :   }
    5949             : 
    5950             :   template <typename ...Args>
    5951             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5952             :   requires EmplaceConstructible<Args...>::value && MoveInsertable
    5953             : #endif
    5954             :   PLUMED_GCH_CPP20_CONSTEXPR
    5955             :   reference
    5956             :   emplace_back (Args&&... args)
    5957             :   {
    5958     2150913 :     return *base::append_element (std::forward<Args> (args)...);
    5959             :   }
    5960             : 
    5961             :   PLUMED_GCH_CPP20_CONSTEXPR
    5962             :   void
    5963             :   pop_back (void)
    5964             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5965             :   requires Erasable
    5966             : #endif
    5967             :   {
    5968             :     assert (! empty () && "`pop_back ()` called on an empty `small_vector`.");
    5969             :     base::erase_last ();
    5970      137267 :   }
    5971             : 
    5972             :   PLUMED_GCH_CPP20_CONSTEXPR
    5973             :   void
    5974             :   reserve (size_type new_capacity)
    5975             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5976             :   requires MoveInsertable
    5977             : #endif
    5978             :   {
    5979       50163 :     base::request_capacity (new_capacity);
    5980       50163 :   }
    5981             : 
    5982             :   PLUMED_GCH_CPP20_CONSTEXPR
    5983             :   void
    5984             :   shrink_to_fit (void)
    5985             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5986             :   requires MoveInsertable
    5987             : #endif
    5988             :   {
    5989             :     base::shrink_to_size ();
    5990             :   }
    5991             : 
    5992             :   PLUMED_GCH_CPP20_CONSTEXPR
    5993             :   void
    5994             :   clear (void) noexcept
    5995             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    5996             :   requires Erasable
    5997             : #endif
    5998             :   {
    5999     1509998 :     base::erase_all ();
    6000             :   }
    6001             : 
    6002             :   PLUMED_GCH_CPP20_CONSTEXPR
    6003             :   void
    6004             :   resize (size_type count)
    6005             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    6006             :   requires MoveInsertable && DefaultInsertable
    6007             : #endif
    6008             :   {
    6009             :     base::resize_with (count);
    6010             :   }
    6011             : 
    6012             :   PLUMED_GCH_CPP20_CONSTEXPR
    6013             :   void
    6014             :   resize (size_type count, const_reference value)
    6015             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    6016             :   requires CopyInsertable
    6017             : #endif
    6018             :   {
    6019             :     base::resize_with (count, value);
    6020             :   }
    6021             : 
    6022             :   PLUMED_GCH_NODISCARD constexpr
    6023             :   bool
    6024             :   inlined (void) const noexcept
    6025             :   {
    6026             :     return ! base::has_allocation ();
    6027             :   }
    6028             : 
    6029             :   PLUMED_GCH_NODISCARD constexpr
    6030             :   bool
    6031             :   inlinable (void) const noexcept
    6032             :   {
    6033             :     return base::is_inlinable ();
    6034             :   }
    6035             : 
    6036             :   PLUMED_GCH_NODISCARD
    6037             :   static PLUMED_GCH_CONSTEVAL
    6038             :   size_type
    6039             :   inline_capacity (void) noexcept
    6040             :   {
    6041             :     return static_cast<size_type> (inline_capacity_v);
    6042             :   }
    6043             : 
    6044             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    6045             :   template <std::input_iterator InputIt>
    6046             :   requires EmplaceConstructible<std::iter_reference_t<InputIt>>::value
    6047             :   &&  MoveInsertable
    6048             : #else
    6049             :   template <typename InputIt,
    6050             :             typename std::enable_if<std::is_base_of<
    6051             :                                       std::input_iterator_tag,
    6052             :                                       typename std::iterator_traits<InputIt>::iterator_category
    6053             :                                       >::value>::type * = nullptr>
    6054             : #endif
    6055             :   PLUMED_GCH_CPP20_CONSTEXPR
    6056             :   small_vector&
    6057             :   append (InputIt first, InputIt last)
    6058             :   {
    6059             :     using policy = typename base::strong_exception_policy;
    6060             :     using iterator_cat = typename std::iterator_traits<InputIt>::iterator_category;
    6061             :     base::template append_range<policy> (first, last, iterator_cat { });
    6062             :     return *this;
    6063             :   }
    6064             : 
    6065             :   PLUMED_GCH_CPP20_CONSTEXPR
    6066             :   small_vector&
    6067             :   append (std::initializer_list<value_type> ilist)
    6068             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    6069             :   requires EmplaceConstructible<const_reference>::value
    6070             :   &&  MoveInsertable
    6071             : #endif
    6072             :   {
    6073             :     return append (ilist.begin (), ilist.end ());
    6074             :   }
    6075             : 
    6076             :   template <unsigned I>
    6077             :   PLUMED_GCH_CPP20_CONSTEXPR
    6078             :   small_vector&
    6079             :   append (const small_vector<T, I, Allocator>& other)
    6080             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    6081             :   requires CopyInsertable
    6082             : #endif
    6083             :   {
    6084             :     return append (other.begin (), other.end ());
    6085             :   }
    6086             : 
    6087             :   template <unsigned I>
    6088             :   PLUMED_GCH_CPP20_CONSTEXPR
    6089             :   small_vector&
    6090             :   append (small_vector<T, I, Allocator>&& other)
    6091             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    6092             :   requires MoveInsertable
    6093             : #endif
    6094             :   {
    6095             :     // Provide a strong exception guarantee for `other` as well.
    6096             :     using move_iter_type = typename std::conditional<
    6097             :       base::template relocate_with_move<value_type>::value,
    6098             :       std::move_iterator<iterator>,
    6099             :       iterator>::type;
    6100             : 
    6101             :     append (move_iter_type { other.begin () }, move_iter_type { other.end () });
    6102             :     other.clear ();
    6103             :     return *this;
    6104             :   }
    6105             : };
    6106             : 
    6107             : template <typename T, unsigned InlineCapacityLHS, unsigned InlineCapacityRHS, typename Allocator>
    6108             : inline PLUMED_GCH_CPP20_CONSTEXPR
    6109             : bool
    6110             : operator== (const small_vector<T, InlineCapacityLHS, Allocator>& lhs,
    6111             :             const small_vector<T, InlineCapacityRHS, Allocator>& rhs)
    6112             : {
    6113             :   return lhs.size () == rhs.size () && std::equal (lhs.begin (), lhs.end (), rhs.begin ());
    6114             : }
    6115             : 
    6116             : template <typename T, unsigned InlineCapacity, typename Allocator>
    6117             : inline PLUMED_GCH_CPP20_CONSTEXPR
    6118             : bool
    6119             : operator== (const small_vector<T, InlineCapacity, Allocator>& lhs,
    6120             :             const small_vector<T, InlineCapacity, Allocator>& rhs)
    6121             : {
    6122             :   return lhs.size () == rhs.size () && std::equal (lhs.begin (), lhs.end (), rhs.begin ());
    6123             : }
    6124             : 
    6125             : #ifdef PLUMED_GCH_LIB_THREE_WAY_COMPARISON
    6126             : 
    6127             : template <typename T, unsigned InlineCapacityLHS, unsigned InlineCapacityRHS, typename Allocator>
    6128             : requires std::three_way_comparable<T>
    6129             : constexpr
    6130             : auto
    6131             : operator<=> (const small_vector<T, InlineCapacityLHS, Allocator>& lhs,
    6132             :              const small_vector<T, InlineCapacityRHS, Allocator>& rhs)
    6133             : {
    6134             :   return std::lexicographical_compare_three_way (
    6135             :     lhs.begin (), lhs.end (),
    6136             :     rhs.begin (), rhs.end (),
    6137             :     std::compare_three_way { });
    6138             : }
    6139             : 
    6140             : template <typename T, unsigned InlineCapacity, typename Allocator>
    6141             : requires std::three_way_comparable<T>
    6142             : constexpr
    6143             : auto
    6144             : operator<=> (const small_vector<T, InlineCapacity, Allocator>& lhs,
    6145             :              const small_vector<T, InlineCapacity, Allocator>& rhs)
    6146             : {
    6147             :   return std::lexicographical_compare_three_way (
    6148             :     lhs.begin (), lhs.end (),
    6149             :     rhs.begin (), rhs.end (),
    6150             :     std::compare_three_way { });
    6151             : }
    6152             : 
    6153             : template <typename T, unsigned InlineCapacityLHS, unsigned InlineCapacityRHS, typename Allocator>
    6154             : constexpr
    6155             : auto
    6156             : operator<=> (const small_vector<T, InlineCapacityLHS, Allocator>& lhs,
    6157             :              const small_vector<T, InlineCapacityRHS, Allocator>& rhs)
    6158             : {
    6159             :   constexpr auto comparison = [](const T& l, const T& r) {
    6160             :     return (l < r) ? std::weak_ordering::less
    6161             :             : (r < l) ? std::weak_ordering::greater
    6162             :                : std::weak_ordering::equivalent;
    6163             :   };
    6164             : 
    6165             :   return std::lexicographical_compare_three_way (
    6166             :            lhs.begin (), lhs.end (),
    6167             :            rhs.begin (), rhs.end (),
    6168             :            comparison);
    6169             : }
    6170             : 
    6171             : template <typename T, unsigned InlineCapacity, typename Allocator>
    6172             : constexpr
    6173             : auto
    6174             : operator<=> (const small_vector<T, InlineCapacity, Allocator>& lhs,
    6175             :              const small_vector<T, InlineCapacity, Allocator>& rhs)
    6176             : {
    6177             :   constexpr auto comparison = [](const T& l, const T& r) {
    6178             :     return (l < r) ? std::weak_ordering::less
    6179             :             : (r < l) ? std::weak_ordering::greater
    6180             :                : std::weak_ordering::equivalent;
    6181             :   };
    6182             : 
    6183             :   return std::lexicographical_compare_three_way (
    6184             :            lhs.begin (), lhs.end (),
    6185             :            rhs.begin (), rhs.end (),
    6186             :            comparison);
    6187             : }
    6188             : 
    6189             : #else
    6190             : 
    6191             : template <typename T, unsigned InlineCapacityLHS, unsigned InlineCapacityRHS, typename Allocator>
    6192             : inline PLUMED_GCH_CPP20_CONSTEXPR
    6193             : bool
    6194             : operator!= (const small_vector<T, InlineCapacityLHS, Allocator>& lhs,
    6195             :             const small_vector<T, InlineCapacityRHS, Allocator>& rhs)
    6196             : {
    6197             :   return ! (lhs == rhs);
    6198             : }
    6199             : 
    6200             : template <typename T, unsigned InlineCapacity, typename Allocator>
    6201             : inline PLUMED_GCH_CPP20_CONSTEXPR
    6202             : bool
    6203             : operator!= (const small_vector<T, InlineCapacity, Allocator>& lhs,
    6204             :             const small_vector<T, InlineCapacity, Allocator>& rhs)
    6205             : {
    6206             :   return ! (lhs == rhs);
    6207             : }
    6208             : 
    6209             : template <typename T, unsigned InlineCapacityLHS, unsigned InlineCapacityRHS, typename Allocator>
    6210             : inline PLUMED_GCH_CPP20_CONSTEXPR
    6211             : bool
    6212             : operator<  (const small_vector<T, InlineCapacityLHS, Allocator>& lhs,
    6213             :             const small_vector<T, InlineCapacityRHS, Allocator>& rhs)
    6214             : {
    6215             :   return std::lexicographical_compare (lhs.begin (), lhs.end (), rhs.begin (), rhs.end ());
    6216             : }
    6217             : 
    6218             : template <typename T, unsigned InlineCapacity, typename Allocator>
    6219             : inline PLUMED_GCH_CPP20_CONSTEXPR
    6220             : bool
    6221             : operator<  (const small_vector<T, InlineCapacity, Allocator>& lhs,
    6222             :             const small_vector<T, InlineCapacity, Allocator>& rhs)
    6223             : {
    6224             :   return std::lexicographical_compare (lhs.begin (), lhs.end (), rhs.begin (), rhs.end ());
    6225             : }
    6226             : 
    6227             : template <typename T, unsigned InlineCapacityLHS, unsigned InlineCapacityRHS, typename Allocator>
    6228             : inline PLUMED_GCH_CPP20_CONSTEXPR
    6229             : bool
    6230             : operator>= (const small_vector<T, InlineCapacityLHS, Allocator>& lhs,
    6231             :             const small_vector<T, InlineCapacityRHS, Allocator>& rhs)
    6232             : {
    6233             :   return ! (lhs < rhs);
    6234             : }
    6235             : 
    6236             : template <typename T, unsigned InlineCapacity, typename Allocator>
    6237             : inline PLUMED_GCH_CPP20_CONSTEXPR
    6238             : bool
    6239             : operator>= (const small_vector<T, InlineCapacity, Allocator>& lhs,
    6240             :             const small_vector<T, InlineCapacity, Allocator>& rhs)
    6241             : {
    6242             :   return ! (lhs < rhs);
    6243             : }
    6244             : 
    6245             : template <typename T, unsigned InlineCapacityLHS, unsigned InlineCapacityRHS, typename Allocator>
    6246             : inline PLUMED_GCH_CPP20_CONSTEXPR
    6247             : bool
    6248             : operator>  (const small_vector<T, InlineCapacityLHS, Allocator>& lhs,
    6249             :             const small_vector<T, InlineCapacityRHS, Allocator>& rhs)
    6250             : {
    6251             :   return rhs < lhs;
    6252             : }
    6253             : 
    6254             : template <typename T, unsigned InlineCapacity, typename Allocator>
    6255             : inline PLUMED_GCH_CPP20_CONSTEXPR
    6256             : bool
    6257             : operator>  (const small_vector<T, InlineCapacity, Allocator>& lhs,
    6258             :             const small_vector<T, InlineCapacity, Allocator>& rhs)
    6259             : {
    6260             :   return rhs < lhs;
    6261             : }
    6262             : 
    6263             : template <typename T, unsigned InlineCapacityLHS, unsigned InlineCapacityRHS, typename Allocator>
    6264             : inline PLUMED_GCH_CPP20_CONSTEXPR
    6265             : bool
    6266             : operator<= (const small_vector<T, InlineCapacityLHS, Allocator>& lhs,
    6267             :             const small_vector<T, InlineCapacityRHS, Allocator>& rhs)
    6268             : {
    6269             :   return rhs >= lhs;
    6270             : }
    6271             : 
    6272             : template <typename T, unsigned InlineCapacity, typename Allocator>
    6273             : inline PLUMED_GCH_CPP20_CONSTEXPR
    6274             : bool
    6275             : operator<= (const small_vector<T, InlineCapacity, Allocator>& lhs,
    6276             :             const small_vector<T, InlineCapacity, Allocator>& rhs)
    6277             : {
    6278             :   return rhs >= lhs;
    6279             : }
    6280             : 
    6281             : #endif
    6282             : 
    6283             : template <typename T, unsigned InlineCapacity, typename Allocator
    6284             : #ifndef PLUMED_GCH_LIB_CONCEPTS
    6285             :           , typename std::enable_if<std::is_move_constructible<T>::value
    6286             :                                     &&  std::is_move_assignable<T>::value
    6287             : #ifdef PLUMED_GCH_LIB_IS_SWAPPABLE
    6288             :                                     &&  std::is_swappable<T>::value
    6289             : #endif
    6290             :                                     >::type * = nullptr
    6291             : #endif
    6292             :           >
    6293             : inline PLUMED_GCH_CPP20_CONSTEXPR
    6294             : void
    6295             : swap (small_vector<T, InlineCapacity, Allocator>& lhs,
    6296             :       small_vector<T, InlineCapacity, Allocator>& rhs)
    6297             : noexcept (noexcept (lhs.swap (rhs)))
    6298             : #ifdef PLUMED_GCH_LIB_CONCEPTS
    6299             : requires concepts::MoveInsertable<T, small_vector<T, InlineCapacity, Allocator>, Allocator>
    6300             : && concepts::Swappable<T>
    6301             : #endif
    6302             : {
    6303             :   lhs.swap (rhs);
    6304             : }
    6305             : 
    6306             : template <typename T, unsigned InlineCapacity, typename Allocator, typename U>
    6307             : inline PLUMED_GCH_CPP20_CONSTEXPR
    6308             : typename small_vector<T, InlineCapacity, Allocator>::size_type
    6309             : erase (small_vector<T, InlineCapacity, Allocator>& v, const U& value)
    6310             : {
    6311             :   const auto original_size = v.size ();
    6312             :   v.erase (std::remove (v.begin (), v.end (), value), v.end ());
    6313             :   return original_size - v.size ();
    6314             : }
    6315             : 
    6316             : template <typename T, unsigned InlineCapacity, typename Allocator, typename Pred>
    6317             : inline PLUMED_GCH_CPP20_CONSTEXPR
    6318             : typename small_vector<T, InlineCapacity, Allocator>::size_type
    6319             : erase_if (small_vector<T, InlineCapacity, Allocator>& v, Pred pred)
    6320             : {
    6321             :   const auto original_size = v.size ();
    6322             :   v.erase (std::remove_if (v.begin (), v.end (), pred), v.end ());
    6323             :   return original_size - v.size ();
    6324             : }
    6325             : 
    6326             : template <typename T, unsigned InlineCapacity, typename Allocator>
    6327             : constexpr
    6328             : typename small_vector<T, InlineCapacity, Allocator>::iterator
    6329             : begin (small_vector<T, InlineCapacity, Allocator>& v) noexcept
    6330             : {
    6331             :   return v.begin ();
    6332             : }
    6333             : 
    6334             : template <typename T, unsigned InlineCapacity, typename Allocator>
    6335             : constexpr
    6336             : typename small_vector<T, InlineCapacity, Allocator>::const_iterator
    6337             : begin (const small_vector<T, InlineCapacity, Allocator>& v) noexcept
    6338             : {
    6339             :   return v.begin ();
    6340             : }
    6341             : 
    6342             : template <typename T, unsigned InlineCapacity, typename Allocator>
    6343             : constexpr
    6344             : typename small_vector<T, InlineCapacity, Allocator>::const_iterator
    6345             : cbegin (const small_vector<T, InlineCapacity, Allocator>& v) noexcept
    6346             : {
    6347             :   return begin (v);
    6348             : }
    6349             : 
    6350             : template <typename T, unsigned InlineCapacity, typename Allocator>
    6351             : constexpr
    6352             : typename small_vector<T, InlineCapacity, Allocator>::iterator
    6353             : end (small_vector<T, InlineCapacity, Allocator>& v) noexcept
    6354             : {
    6355             :   return v.end ();
    6356             : }
    6357             : 
    6358             : template <typename T, unsigned InlineCapacity, typename Allocator>
    6359             : constexpr
    6360             : typename small_vector<T, InlineCapacity, Allocator>::const_iterator
    6361             : end (const small_vector<T, InlineCapacity, Allocator>& v) noexcept
    6362             : {
    6363             :   return v.end ();
    6364             : }
    6365             : 
    6366             : template <typename T, unsigned InlineCapacity, typename Allocator>
    6367             : constexpr
    6368             : typename small_vector<T, InlineCapacity, Allocator>::const_iterator
    6369             : cend (const small_vector<T, InlineCapacity, Allocator>& v) noexcept
    6370             : {
    6371             :   return end (v);
    6372             : }
    6373             : 
    6374             : template <typename T, unsigned InlineCapacity, typename Allocator>
    6375             : constexpr
    6376             : typename small_vector<T, InlineCapacity, Allocator>::reverse_iterator
    6377             : rbegin (small_vector<T, InlineCapacity, Allocator>& v) noexcept
    6378             : {
    6379             :   return v.rbegin ();
    6380             : }
    6381             : 
    6382             : template <typename T, unsigned InlineCapacity, typename Allocator>
    6383             : constexpr
    6384             : typename small_vector<T, InlineCapacity, Allocator>::const_reverse_iterator
    6385             : rbegin (const small_vector<T, InlineCapacity, Allocator>& v) noexcept
    6386             : {
    6387             :   return v.rbegin ();
    6388             : }
    6389             : 
    6390             : template <typename T, unsigned InlineCapacity, typename Allocator>
    6391             : constexpr
    6392             : typename small_vector<T, InlineCapacity, Allocator>::const_reverse_iterator
    6393             : crbegin (const small_vector<T, InlineCapacity, Allocator>& v) noexcept
    6394             : {
    6395             :   return rbegin (v);
    6396             : }
    6397             : 
    6398             : template <typename T, unsigned InlineCapacity, typename Allocator>
    6399             : constexpr
    6400             : typename small_vector<T, InlineCapacity, Allocator>::reverse_iterator
    6401             : rend (small_vector<T, InlineCapacity, Allocator>& v) noexcept
    6402             : {
    6403             :   return v.rend ();
    6404             : }
    6405             : 
    6406             : template <typename T, unsigned InlineCapacity, typename Allocator>
    6407             : constexpr
    6408             : typename small_vector<T, InlineCapacity, Allocator>::const_reverse_iterator
    6409             : rend (const small_vector<T, InlineCapacity, Allocator>& v) noexcept
    6410             : {
    6411             :   return v.rend ();
    6412             : }
    6413             : 
    6414             : template <typename T, unsigned InlineCapacity, typename Allocator>
    6415             : constexpr
    6416             : typename small_vector<T, InlineCapacity, Allocator>::const_reverse_iterator
    6417             : crend (const small_vector<T, InlineCapacity, Allocator>& v) noexcept
    6418             : {
    6419             :   return rend (v);
    6420             : }
    6421             : 
    6422             : template <typename T, unsigned InlineCapacity, typename Allocator>
    6423             : constexpr
    6424             : typename small_vector<T, InlineCapacity, Allocator>::size_type
    6425             : size (const small_vector<T, InlineCapacity, Allocator>& v) noexcept
    6426             : {
    6427             :   return v.size ();
    6428             : }
    6429             : 
    6430             : template <typename T, unsigned InlineCapacity, typename Allocator>
    6431             : constexpr
    6432             : typename std::common_type<
    6433             :   std::ptrdiff_t,
    6434             :   typename std::make_signed<
    6435             :     typename small_vector<T, InlineCapacity, Allocator>::size_type>::type>::type
    6436             : ssize (const small_vector<T, InlineCapacity, Allocator>& v) noexcept
    6437             : {
    6438             :   using ret_type = typename std::common_type<
    6439             :     std::ptrdiff_t,
    6440             :     typename std::make_signed<decltype (v.size ())>::type>::type;
    6441             :   return static_cast<ret_type> (v.size ());
    6442             : }
    6443             : 
    6444             : template <typename T, unsigned InlineCapacity, typename Allocator>
    6445             : PLUMED_GCH_NODISCARD constexpr
    6446             : bool
    6447             : empty (const small_vector<T, InlineCapacity, Allocator>& v) noexcept
    6448             : {
    6449             :   return v.empty ();
    6450             : }
    6451             : 
    6452             : template <typename T, unsigned InlineCapacity, typename Allocator>
    6453             : constexpr
    6454             : typename small_vector<T, InlineCapacity, Allocator>::pointer
    6455             : data (small_vector<T, InlineCapacity, Allocator>& v) noexcept
    6456             : {
    6457             :   return v.data ();
    6458             : }
    6459             : 
    6460             : template <typename T, unsigned InlineCapacity, typename Allocator>
    6461             : constexpr
    6462             : typename small_vector<T, InlineCapacity, Allocator>::const_pointer
    6463             : data (const small_vector<T, InlineCapacity, Allocator>& v) noexcept
    6464             : {
    6465             :   return v.data ();
    6466             : }
    6467             : 
    6468             : #ifdef PLUMED_GCH_CTAD_SUPPORT
    6469             : 
    6470             : template <typename InputIt,
    6471             :           unsigned InlineCapacity = default_buffer_size<
    6472             :             std::allocator<typename std::iterator_traits<InputIt>::value_type>>::value,
    6473             :           typename Allocator = std::allocator<typename std::iterator_traits<InputIt>::value_type>>
    6474             : small_vector (InputIt, InputIt, Allocator = Allocator ())
    6475             : -> small_vector<typename std::iterator_traits<InputIt>::value_type, InlineCapacity, Allocator>;
    6476             : 
    6477             : #endif
    6478             : 
    6479             : } // namespace gch
    6480             : } // namespace PLMD
    6481             : 
    6482             : #endif // PLUMED_GCH_SMALL_VECTOR_HPP
    6483             : #endif

Generated by: LCOV version 1.16