On Mon, 9 Feb 2026 at 15:19, Patrick Palka <[email protected]> wrote:
>
> Changes in v2:
>  - Rebased
>
> This patch mechanically removes _Executor's __dfs_mode template
> parameter.  In passing we can also get rid of the _V2 inline namespace
> because this change is sufficient to make all of _Executor's member
> function signatures different from the previous (GCC <= 15) recursive
> implementation, so that mixing the two implementations won't conflict.

OK


>
> libstdc++-v3/ChangeLog:
>
>         * include/bits/regex.h (_Executor): Remove __dfs_mode template
>         parameter and _V2 inline namespace.
>         * include/bits/regex.tcc (__regex_algo_impl): Adjust after
>         __dfs_mode template parameter removal.
>         * include/bits/regex_executor.h (_Executor): Remove __dfs_mode
>         parameter and _V2 inline namespace.
>         * include/bits/regex_executor.tcc (_Executor): Likewise.
> ---
>  libstdc++-v3/include/bits/regex.h            |  8 +-
>  libstdc++-v3/include/bits/regex.tcc          |  2 +-
>  libstdc++-v3/include/bits/regex_executor.h   |  7 +-
>  libstdc++-v3/include/bits/regex_executor.tcc | 97 ++++++++------------
>  4 files changed, 44 insertions(+), 70 deletions(-)
>
> diff --git a/libstdc++-v3/include/bits/regex.h 
> b/libstdc++-v3/include/bits/regex.h
> index 5bcb9a447ce2..0e815ca086eb 100644
> --- a/libstdc++-v3/include/bits/regex.h
> +++ b/libstdc++-v3/include/bits/regex.h
> @@ -61,10 +61,8 @@ namespace __detail
>                       _RegexExecutorPolicy                 __policy,
>                       bool                                 __match_mode);
>
> -_GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
> -  template<typename, typename, typename, bool>
> +  template<typename, typename, typename>
>      class _Executor;
> -_GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
>
>    template<typename _Tp>
>      struct __is_contiguous_iter : false_type { };
> @@ -842,7 +840,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
>                                     regex_constants::match_flag_type,
>                                     __detail::_RegexExecutorPolicy, bool);
>
> -      template<typename, typename, typename, bool>
> +      template<typename, typename, typename>
>         friend class __detail::_Executor;
>
>        flag_type                _M_flags;
> @@ -2136,7 +2134,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
>
>        /// @cond undocumented
>
> -      template<typename, typename, typename, bool>
> +      template<typename, typename, typename>
>         friend class __detail::_Executor;
>
>        template<typename _Bp, typename _Ap, typename _Cp, typename _Rp>
> diff --git a/libstdc++-v3/include/bits/regex.tcc 
> b/libstdc++-v3/include/bits/regex.tcc
> index d16cfd5baf01..ca500d21c348 100644
> --- a/libstdc++-v3/include/bits/regex.tcc
> +++ b/libstdc++-v3/include/bits/regex.tcc
> @@ -67,7 +67,7 @@ namespace __detail
>               && !__re._M_automaton->_M_has_backref))
>         __use_dfs = false;
>
> -      _Executor<_BiIter, _Alloc, _TraitsT, true>
> +      _Executor<_BiIter, _Alloc, _TraitsT>
>         __executor(__s, __e, __res, __re, __flags, __use_dfs);
>        if (__match_mode)
>         __ret = __executor._M_match();
> diff --git a/libstdc++-v3/include/bits/regex_executor.h 
> b/libstdc++-v3/include/bits/regex_executor.h
> index 2638df4d5afb..797ad702784b 100644
> --- a/libstdc++-v3/include/bits/regex_executor.h
> +++ b/libstdc++-v3/include/bits/regex_executor.h
> @@ -36,7 +36,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>
>  namespace __detail
>  {
> -_GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
>    /**
>     * @addtogroup regex-detail
>     * @{
> @@ -49,10 +48,9 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
>     * @brief Takes a regex and an input string and does the matching.
>     *
>     * The %_Executor class has two modes: DFS mode and BFS mode, controlled
> -   * by the template parameter %__dfs_mode.
> +   * by the function parameter %__search_mode.
>     */
> -  template<typename _BiIter, typename _Alloc, typename _TraitsT,
> -          bool __dfs_mode>
> +  template<typename _BiIter, typename _Alloc, typename _TraitsT>
>      class _Executor
>      {
>        enum class _Search_mode : unsigned char { _BFS = 0, _DFS = 1 };
> @@ -287,7 +285,6 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
>      };
>
>   ///@} regex-detail
> -_GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
>  } // namespace __detail
>  _GLIBCXX_END_NAMESPACE_VERSION
>  } // namespace std
> diff --git a/libstdc++-v3/include/bits/regex_executor.tcc 
> b/libstdc++-v3/include/bits/regex_executor.tcc
> index 0ae7bdf6839a..4eda6bdf5531 100644
> --- a/libstdc++-v3/include/bits/regex_executor.tcc
> +++ b/libstdc++-v3/include/bits/regex_executor.tcc
> @@ -36,10 +36,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>  #pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
>  namespace __detail
>  {
> -_GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
> -  template<typename _BiIter, typename _Alloc, typename _TraitsT,
> -          bool __dfs_mode>
> -    bool _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
> +  template<typename _BiIter, typename _Alloc, typename _TraitsT>
> +    bool _Executor<_BiIter, _Alloc, _TraitsT>::
>      _M_search()
>      {
>        if (_M_search_from_first())
> @@ -160,9 +158,8 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
>    // Time complexity: \Omega(match_length), O(2^(_M_nfa.size()))
>    // Space complexity: \theta(match_results.size() + match_length)
>    //
> -  template<typename _BiIter, typename _Alloc, typename _TraitsT,
> -          bool __dfs_mode>
> -    bool _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
> +  template<typename _BiIter, typename _Alloc, typename _TraitsT>
> +    bool _Executor<_BiIter, _Alloc, _TraitsT>::
>      _M_main_dfs(_Match_mode __match_mode)
>      {
>        _M_has_sol = false;
> @@ -194,9 +191,8 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
>    //                  O(match_length * _M_nfa.size() * match_results.size())
>    // Space complexity: \Omega(_M_nfa.size() + match_results.size())
>    //                   O(_M_nfa.size() * match_results.size())
> -  template<typename _BiIter, typename _Alloc, typename _TraitsT,
> -          bool __dfs_mode>
> -    bool _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
> +  template<typename _BiIter, typename _Alloc, typename _TraitsT>
> +    bool _Executor<_BiIter, _Alloc, _TraitsT>::
>      _M_main_bfs(_Match_mode __match_mode)
>      {
>        _M_match_queue.emplace_back(_M_start, _M_results);
> @@ -227,9 +223,8 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
>      }
>
>    // Return whether now match the given sub-NFA.
> -  template<typename _BiIter, typename _Alloc, typename _TraitsT,
> -          bool __dfs_mode>
> -    bool _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
> +  template<typename _BiIter, typename _Alloc, typename _TraitsT>
> +    bool _Executor<_BiIter, _Alloc, _TraitsT>::
>      _M_lookahead(_StateIdT __next)
>      {
>        // Backreferences may refer to captured content.
> @@ -255,9 +250,8 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
>    // infinite loop by refusing to continue when it's already been
>    // visited more than twice. It's `twice` instead of `once` because
>    // we need to spare one more time for potential group capture.
> -  template<typename _BiIter, typename _Alloc, typename _TraitsT,
> -          bool __dfs_mode>
> -    void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
> +  template<typename _BiIter, typename _Alloc, typename _TraitsT>
> +    void _Executor<_BiIter, _Alloc, _TraitsT>::
>      _M_rep_once_more(_Match_mode __match_mode, _StateIdT __i)
>      {
>        const auto& __state = _M_nfa[__i];
> @@ -286,9 +280,8 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
>    // of this quantifier". Executing _M_next first or _M_alt first don't
>    // mean the same thing, and we need to choose the correct order under
>    // given greedy mode.
> -  template<typename _BiIter, typename _Alloc, typename _TraitsT,
> -          bool __dfs_mode>
> -    void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
> +  template<typename _BiIter, typename _Alloc, typename _TraitsT>
> +    void _Executor<_BiIter, _Alloc, _TraitsT>::
>      _M_handle_repeat(_Match_mode __match_mode, _StateIdT __i)
>      {
>        const auto& __state = _M_nfa[__i];
> @@ -329,9 +322,8 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
>         }
>      }
>
> -  template<typename _BiIter, typename _Alloc, typename _TraitsT,
> -          bool __dfs_mode>
> -    void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
> +  template<typename _BiIter, typename _Alloc, typename _TraitsT>
> +    void _Executor<_BiIter, _Alloc, _TraitsT>::
>      _M_handle_subexpr_begin(_Match_mode __match_mode, _StateIdT __i)
>      {
>        const auto& __state = _M_nfa[__i];
> @@ -343,9 +335,8 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
>        _M_frames.emplace_back(_S_fopcode_next, __state._M_next);
>      }
>
> -  template<typename _BiIter, typename _Alloc, typename _TraitsT,
> -          bool __dfs_mode>
> -    void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
> +  template<typename _BiIter, typename _Alloc, typename _TraitsT>
> +    void _Executor<_BiIter, _Alloc, _TraitsT>::
>      _M_handle_subexpr_end(_Match_mode __match_mode, _StateIdT __i)
>      {
>        const auto& __state = _M_nfa[__i];
> @@ -360,9 +351,8 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
>        _M_frames.emplace_back(_S_fopcode_next, __state._M_next);
>      }
>
> -  template<typename _BiIter, typename _Alloc, typename _TraitsT,
> -          bool __dfs_mode>
> -    inline void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
> +  template<typename _BiIter, typename _Alloc, typename _TraitsT>
> +    inline void _Executor<_BiIter, _Alloc, _TraitsT>::
>      _M_handle_line_begin_assertion(_Match_mode __match_mode, _StateIdT __i)
>      {
>        const auto& __state = _M_nfa[__i];
> @@ -370,9 +360,8 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
>         _M_frames.emplace_back(_S_fopcode_next, __state._M_next);
>      }
>
> -  template<typename _BiIter, typename _Alloc, typename _TraitsT,
> -          bool __dfs_mode>
> -    inline void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
> +  template<typename _BiIter, typename _Alloc, typename _TraitsT>
> +    inline void _Executor<_BiIter, _Alloc, _TraitsT>::
>      _M_handle_line_end_assertion(_Match_mode __match_mode, _StateIdT __i)
>      {
>        const auto& __state = _M_nfa[__i];
> @@ -380,9 +369,8 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
>         _M_frames.emplace_back(_S_fopcode_next, __state._M_next);
>      }
>
> -  template<typename _BiIter, typename _Alloc, typename _TraitsT,
> -          bool __dfs_mode>
> -    inline void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
> +  template<typename _BiIter, typename _Alloc, typename _TraitsT>
> +    inline void _Executor<_BiIter, _Alloc, _TraitsT>::
>      _M_handle_word_boundary(_Match_mode __match_mode, _StateIdT __i)
>      {
>        const auto& __state = _M_nfa[__i];
> @@ -392,9 +380,8 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
>
>    // Here __state._M_alt offers a single start node for a sub-NFA.
>    // We recursively invoke our algorithm to match the sub-NFA.
> -  template<typename _BiIter, typename _Alloc, typename _TraitsT,
> -          bool __dfs_mode>
> -    void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
> +  template<typename _BiIter, typename _Alloc, typename _TraitsT>
> +    void _Executor<_BiIter, _Alloc, _TraitsT>::
>      _M_handle_subexpr_lookahead(_Match_mode __match_mode, _StateIdT __i)
>      {
>        const auto& __state = _M_nfa[__i];
> @@ -402,9 +389,8 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
>         _M_frames.emplace_back(_S_fopcode_next, __state._M_next);
>      }
>
> -  template<typename _BiIter, typename _Alloc, typename _TraitsT,
> -          bool __dfs_mode>
> -    void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
> +  template<typename _BiIter, typename _Alloc, typename _TraitsT>
> +    void _Executor<_BiIter, _Alloc, _TraitsT>::
>      _M_handle_match(_Match_mode __match_mode, _StateIdT __i)
>      {
>        const auto& __state = _M_nfa[__i];
> @@ -475,9 +461,8 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
>    // then compare it with
>    // (_M_current, _M_current + (__submatch.second - __submatch.first)).
>    // If matched, keep going; else just return and try another state.
> -  template<typename _BiIter, typename _Alloc, typename _TraitsT,
> -          bool __dfs_mode>
> -    void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
> +  template<typename _BiIter, typename _Alloc, typename _TraitsT>
> +    void _Executor<_BiIter, _Alloc, _TraitsT>::
>      _M_handle_backref(_Match_mode __match_mode, _StateIdT __i)
>      {
>        __glibcxx_assert(_M_search_mode == _Search_mode::_DFS);
> @@ -501,9 +486,8 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
>         }
>      }
>
> -  template<typename _BiIter, typename _Alloc, typename _TraitsT,
> -          bool __dfs_mode>
> -    void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
> +  template<typename _BiIter, typename _Alloc, typename _TraitsT>
> +    void _Executor<_BiIter, _Alloc, _TraitsT>::
>      _M_handle_accept(_Match_mode __match_mode, _StateIdT)
>      {
>        if (_M_search_mode == _Search_mode::_DFS)
> @@ -554,9 +538,8 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
>         }
>      }
>
> -  template<typename _BiIter, typename _Alloc, typename _TraitsT,
> -          bool __dfs_mode>
> -    void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
> +  template<typename _BiIter, typename _Alloc, typename _TraitsT>
> +    void _Executor<_BiIter, _Alloc, _TraitsT>::
>      _M_handle_alternative(_Match_mode __match_mode, _StateIdT __i)
>      {
>        const auto& __state = _M_nfa[__i];
> @@ -578,12 +561,11 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
>         }
>      }
>
> -  template<typename _BiIter, typename _Alloc, typename _TraitsT,
> -          bool __dfs_mode>
> +  template<typename _BiIter, typename _Alloc, typename _TraitsT>
>  #ifdef __OPTIMIZE__
>      [[__gnu__::__always_inline__]]
>  #endif
> -    inline void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
> +    inline void _Executor<_BiIter, _Alloc, _TraitsT>::
>      _M_node(_Match_mode __match_mode, _StateIdT __i)
>      {
>        if (_M_visited(__i))
> @@ -622,9 +604,8 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
>         }
>      }
>
> -  template<typename _BiIter, typename _Alloc, typename _TraitsT,
> -          bool __dummy>
> -    void _Executor<_BiIter, _Alloc, _TraitsT, __dummy>::
> +  template<typename _BiIter, typename _Alloc, typename _TraitsT>
> +    void _Executor<_BiIter, _Alloc, _TraitsT>::
>      _M_dfs(_Match_mode __match_mode, _StateIdT __start)
>      {
>        const bool __dfs_mode = (_M_search_mode == _Search_mode::_DFS);
> @@ -692,9 +673,8 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
>      }
>
>    // Return whether now is at some word boundary.
> -  template<typename _BiIter, typename _Alloc, typename _TraitsT,
> -          bool __dfs_mode>
> -    bool _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
> +  template<typename _BiIter, typename _Alloc, typename _TraitsT>
> +    bool _Executor<_BiIter, _Alloc, _TraitsT>::
>      _M_word_boundary() const
>      {
>        if (_M_current == _M_begin && (_M_flags & 
> regex_constants::match_not_bow))
> @@ -715,7 +695,6 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
>
>        return __left_is_word != __right_is_word;
>      }
> -_GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
>  } // namespace __detail
>  #pragma GCC diagnostic pop
>
> --
> 2.53.0.40.g3e0db84c88
>

Reply via email to