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

Generated by: LCOV version 1.16