Message ID | CAH6eHdSRGuFm_oMJnjLniZFw2nKdnKncCowOv_o4M7Ud3xgiLQ@mail.gmail.com |
---|---|
State | New |
Headers | show |
2013/11/8 Jonathan Wakely <jwakely.gcc@gmail.com>: > As I suggested yesterday on the libstdc++ list, this adds an overload > for string and vector iterators to extract a raw pointer and re-use > the _Compiler<const C*,...> specialization, so that std::regex(".") > and std::regex(std::string(".")) and std::regex(std::vector<char>(1, > '.')) only instantiate _Compiler<It,Tr> once. > > 2013-11-08 Jonathan Wakely <jwakely.gcc@gmail.com> > > * include/bits/regex_compiler.h (__detail::__compile_nfa): Overload > so that std::basic_string<C> and std::vector<C> iterators dispatch to > the const C* compiler. I have fully not grasped for which T the specializations of __has_contiguous_iter are intended to be used, but given the fact that + template<typename _Tp, typename _Alloc> + struct __has_contiguous_iter<std::vector<_Tp, _Alloc>> + : std::true_type + { }; exists I think you really want to exclude any vector<bool, Allocator> by additionally adding + template<typename _Alloc> + struct __has_contiguous_iter<std::vector<bool, _Alloc>> + : std::false_type + { }; - Daniel
On 8 November 2013 14:51, Daniel Krügler wrote: > I have fully not grasped for which T the specializations of > __has_contiguous_iter are intended to be used, Currently, only std::container iterators passed to a basic_regex constructor, but in theory the trait could get moved to another header and used elsewhere in future. > but given the fact that > > + template<typename _Tp, typename _Alloc> > + struct __has_contiguous_iter<std::vector<_Tp, _Alloc>> > + : std::true_type > + { }; > > exists I think you really want to exclude any vector<bool, Allocator> > by additionally adding > > + template<typename _Alloc> > + struct __has_contiguous_iter<std::vector<bool, _Alloc>> > + : std::false_type > + { }; Hmm, I didn't think of that, damn vector<bool>! It's only needed in case someone does this: std::vector<bool> v; std::regex re(v.begin(), v.end()); which would be pretty crazy, but it has well-defined behaviour and should throw regex_error. I'll add the specialization, thanks for catching it.
On 8 November 2013 15:41, Jonathan Wakely wrote: > On 8 November 2013 14:51, Daniel Krügler wrote: >> I have fully not grasped for which T the specializations of >> __has_contiguous_iter are intended to be used, > > Currently, only std::container iterators passed to a basic_regex > constructor, but in theory the trait could get moved to another header > and used elsewhere in future. Currently the vector<bool> specialization can never be reached, because std::vector<bool> doesn't use __gnu_cxx::__normal_iterator (and trying to pass vector<bool>::iterator to a regex ctor fails anyway) so this is only a theoretical problem if we re-use __has_contiguous_iter elsewhere.
diff --git a/libstdc++-v3/include/bits/regex_compiler.h b/libstdc++-v3/include/bits/regex_compiler.h index 406d9a9..741098f 100644 --- a/libstdc++-v3/include/bits/regex_compiler.h +++ b/libstdc++-v3/include/bits/regex_compiler.h @@ -129,8 +129,40 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _StackT _M_stack; }; + template<typename _Tp> + struct __has_contiguous_iter : std::false_type { }; + + template<typename _Ch, typename _Tr, typename _Alloc> + struct __has_contiguous_iter<std::basic_string<_Ch, _Tr, _Alloc>> + : std::true_type + { }; + + template<typename _Tp, typename _Alloc> + struct __has_contiguous_iter<std::vector<_Tp, _Alloc>> + : std::true_type + { }; + + template<typename _Tp> + struct __is_contiguous_normal_iter : std::false_type { }; + + template<typename _Tp, typename _Cont> + struct + __is_contiguous_normal_iter<__gnu_cxx::__normal_iterator<_Tp, _Cont>> + : __has_contiguous_iter<_Cont>::type + { }; + + template<typename _Iter, typename _TraitsT> + using __enable_if_contiguous_normal_iter + = typename enable_if< __is_contiguous_normal_iter<_Iter>::value, + std::shared_ptr<_NFA<_TraitsT>> >::type; + + template<typename _Iter, typename _TraitsT> + using __disable_if_contiguous_normal_iter + = typename enable_if< !__is_contiguous_normal_iter<_Iter>::value, + std::shared_ptr<_NFA<_TraitsT>> >::type; + template<typename _FwdIter, typename _TraitsT> - inline std::shared_ptr<_NFA<_TraitsT>> + inline __disable_if_contiguous_normal_iter<_FwdIter, _TraitsT> __compile_nfa(_FwdIter __first, _FwdIter __last, const _TraitsT& __traits, regex_constants::syntax_option_type __flags) { @@ -138,6 +170,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return _Cmplr(__first, __last, __traits, __flags)._M_get_nfa(); } + template<typename _Iter, typename _TraitsT> + inline __enable_if_contiguous_normal_iter<_Iter, _TraitsT> + __compile_nfa(_Iter __first, _Iter __last, const _TraitsT& __traits, + regex_constants::syntax_option_type __flags) + { + size_t __len = __last - __first; + const auto* __cfirst = __len ? std::__addressof(*__first) : nullptr; + return __compile_nfa(__cfirst, __cfirst + __len, __traits, __flags); + } + template<typename _TraitsT> struct _AnyMatcher {