1. Changelog
- 
     R1 - 
       Rebased on top of the latest Standard draft. 
- 
       Renamed the trait for Option 1, and split the option into two sub-options. 
 
- 
       
- 
     R0 - 
       First submission 
 
- 
       
2. Motivation and Scope
[P1989R2] added a new constructor to 
[P2499R0] subsequently modified this constructor, by making it unconditionally 
The reasoning for this change was that not all compatible ranges are convertible to a string view by using their own size (the "range size"). In many important use cases, the size that is meant to be used is the "
For instance, [P2499R0] has this example featuring "Modern C++" datatypes:
extern void get_string ( std :: span < char > buffer ); extern void use_string ( std :: string_view str ); std :: array < char , 200 > buf ; get_string ( buf ); use_string ( buf ); // oops 
This code used to compile before [P2499R0]. However: if the semantics of 
This change has a few consequences.
First and foremost it’s worth underlying that the proposed solution is still somehow a band-aid for this sort of use cases. If one uses 
Second, and more in general; in a sense, the proposed change splits the types that can be converted to a string view in two families:
- 
     types for which we now axiomatically establish that their size is always the "range size", and these convert implictly (e.g. std :: string 
- 
     types for which don’t necessarily know which one is the "correct" size, and those must be converted explicitly after [P2499R0] (e.g. std :: vector < char > 
The problem with split (and in particular with 2.) is that it fundamentally kills the usability of string views as an universal interface type for read-only non-owning string-like inputs.
For instance, if one has a string type different than 
void use ( std :: string_view v ); std :: string str1 ; use ( str1 ); // OK my :: string str2 ; use ( str2 ); // ERROR 
Unless 
So, what’s the problem, just provide the operator, like 
This usability impedance is there also if one goes in the opposite direction. Suppose one has a 
Then:
void lib::very_useful_algorithm ( lib :: string_view v ); std :: string str ; lib :: very_useful_algorithm ( str ); // ERROR 
There is absolutely no reason why the above shouldn’t compile. 
Alas, that’s not the case (due to explicit construction from a range), and since we cannot modify either datatype (both belong to 3rd parties), we must add explicit conversions everywhere. This is completely anti-ergonomic for users.
The idea of adding conversion constructors/operators also does not scale. Again assuming that any 3rd party string view implementation follows [P2499R0]'s design, should the author of 
In Qt, the author implemented the same semantic change of P2499R0 for Qt’s string view classes. The result was that certain implicit conversions got broken, such as from 
What we are highlighting here is that there is tension between the safety concerns behind the changes proposed by [P2499R0]'s, and the usefulness of string views as a vocabulary interface type -- usefulness that gets dramatically reduced (or removed, one could say) by making the range conversion unconditionally explicit.
We could restore most of this usefulness by making the range conversion implicit in the cases where we know it’s safe to do. The only problematic aspect is: how to identify those cases?
3. Design Decisions
3.1. How to identify a string(view) class?
Unfortunately there isn’t an universal way to identify all and only string(view)-like classes for which we’d like to enable implicit conversions towards string views. As far as their range properties are concerned, a 
We need therefore a trait, which necessarily needs to be opt-in. The point is that we want to err on the side of caution: for an arbitrary contiguous range we want to keep the conversion explicit. A string(view)-like class can enable the opt-in and become implicitly convertible instead, and string view classes such as 
There are two alternatives for the design of such a trait.
- 
     We can introduce a brand new type trait to specialize, and/or a class to inherit from, similar to various other precedents in the Standard Library (for instance, std :: ranges :: enable_view < T > 
- 
     We can use some "unique" feature of string(view)-like types. Specifically, this paper proposes to detect the presence and compatibility of an inner traits_type 
Both of these options have some downsides.
- 
     In general, both options require an opt-in from existing code. However there is already significant production code that implements approach 2, like std :: string std :: string_view folly :: fbstring boost :: string_view absl :: string_view 
- 
     The inner traits_type It sounds pretty unlikely that a compatible range declares a compatible traits_type traits_type traits_type basic_string basic_string_view basic_regex basic_ios basic_string basic_string_view Nonetheless, we sampled various projects in order to back this claim with some real-world data. The results are: Project Findings Folly Only used in fbstring LLVM (excluding libcxx and tests) Used by OpenMP in some flag types ( kmp_flag kmp_flag_native kmp_flag_atomic Abseil Only used in string_view std :: string_view Firefox According to Searchfox, only 3rd party code (Abseil, protobuf) defines a traits_type Range-v3 Used in the ostream iterators like ostream_iterator Qt There are no occurrences of traits_type Boost Boost has a considerable number of usages, about 140 (a complete listing is in Appendix A: traits_type in Boost 1.81), the majority of which are not string related classes at all. This indeed shows that the traits_type Still, there’s a non-trivial amount of string(view)-like classes. Adding transparent interoperability would be a major usability win. Amongst the string classes, these are compatible with basic_string_view traits_type - 
           In Container, basic_string 
- 
           In Core there’s an internal basic_string_view 
- 
           In Log, there’s an internal basic_string_literal 
- 
           In StaticString, basic_static_string 
- 
           In Process V2, basic_cstring_ref key_view value_view key_value_pair_view 
- 
           In Test, basic_cstring 
- 
           In Url, pct_string_view 
- 
           In Utility, string_view 
- 
           In Wave, flex_string 
 There’s also some non compatible string class: - 
           In Compute, basic_string traits_type 
 In the rest of usages, the containing datatype is not a range at all, and/or traits_type basic_string_view In conclusion, these results strongly point towards the conclusion that only string(view)-like types are detected: the detection is correct. It is not complete: types such as QString QStringView llvm :: StringRef traits_type traits_type 
- 
           
- 
     A downside of option 1 is the timing aspect. Adding a brand new trait would mean crippling string views for one additional C++ version cycle, until one can use a C++26 (?) compiler that adds the trait and one can use it. Option 2 could (and in our opinion should) be treated as a defect fix instead. 
Given the results above, the author’s preference would be for option 2, but we would like to gather feedback from SG9, SG16 and LEWG.
3.2. Is this a defect fix?
If option 2 is chosen, we would prefer that the changes proposed by this paper would be considered as a defect fix by implementors and backported to their C++23 modes. For this reason we would not be proposing any new feature-testing macro, nor to bump the value of an existing one. (The change is still entirely detectable by users via type traits, should the need arise.)
Option 1 is fundamentally a brand new API, so it cannot be considered a fix.
4. Impact on the Standard
This proposal is a pure library change. Depending on the option chosen, it may extend/change the proposed resolution to [LWG3857].
The impact is strictly positive: code that was ill-formed (after [P2499R0]) becomes well-formed.
5. Technical Specifications
All the proposed changes are relative to [N4928].
6. Proposed wording
6.1. Option 1: introduce a dedicated type trait
We are proposing two slightly different alternatives for Option 1.
In the first alternative (1-A) we entirely ignore the compatibility of character traits between the type of the string(view)-like input range, and the character traits of the string view. An string(view)-like input range that opts in the trait signals its intention to be implicitly convertible towards string views even if these latter use different/incompatible character traits.
We realize this might be undesirable, so we are also proposing a second alternative (1-B). In this second alternative we add two type traits/enablers, one that does not take character traits into account (
- 
     if the string view class does not care about character traits (e.g. QStringView enable_string_view_conversion 
- 
     if the string view class cares (e.g. std :: string_view enable_string_view_conversion_with_traits 
Symmetrically, a string(view)-like class can always enable the more generic trait, but also decide how to handle a "conversion request" that takes traits into account. For instance, it may check that the requested traits match or are compatible the class' own traits (e.g. 
Here we would like SG16 input to determine the best course of action.
Both option 1-A and 1-B add a new feature-testing macro.
6.1.1. Option 1-A: introduce a type trait that does not take character traits into account
Add to the list in [version.syn]:
#define __cpp_lib_enable_string_view_conversion YYYYMML // also in <string_view> 
with the 
Modify [string.view.synop] as follows:
// [string.view.template], class template basic_string_view template < class charT , class traits = char_traits < charT >> class basic_string_view ; template < class T > constexpr bool enable_string_view_conversion = false; template < class charT , class traits > constexpr bool enable_string_view_conversion < basic_string_view < charT , traits >> = true; 
Add a new section after [string.view.literals]:
23.4 Enablers for implicit string view construction from ranges [string.view.range.construction]1. Remarks: Pursuant to [namespace.std], users may specializetemplate < class T > constexpr bool enable_string_view_conversion = false; for cv-unqualified program-defined types. Such specializations shall be usable in constant expressions ([expr.const]) and have typeenable_string_view_conversion .const bool 
Modify [string.syn] as follows:
// [basic.string], basic_string template < class charT , class traits = char_traits < charT > , class Allocator = allocator < charT >> class basic_string ; template < class charT , class traits , class Allocator > constexpr bool enable_string_view_conversion < basic_string < charT , traits , Allocator >> = true; 
Modify [string.view.template.general] as shown:
template < class R > constexpr explicit ( see below ) basic_string_view ( R && r ); 
Modify [string.view.cons] as shown:
template < class R > constexpr explicit ( see below ) basic_string_view ( R && r ); 
Let
be an lvalue of typed .remove_cvref_t < R > 
Constraints:
(12.1) —
is not the same type asremove_cvref_t < R > ,basic_string_view (12.2) —
modelsR andranges :: contiguous_range ,ranges :: sized_range (12.3) —
isis_same_v < ranges :: range_value_t < R > , charT > true,(12.4) —
isis_convertible_v < R , const charT *> false, and(12.5) —
is not a valid expression.d . operator :: std :: basic_string_view < charT , traits > () 15. Remarks: The expression inside
Effects: Initializes
 withdata_ andranges :: data ( r )  withsize_ .ranges :: size ( r ) 
Throws: Any exception thrown by
andranges :: data ( r ) .ranges :: size ( r ) is equivalent toexplicit .! enable_string_view_conversion < remove_cvref_t < R >> 
6.1.2. Option 1-B: introduce type traits that take character traits into account
Add to the list in [version.syn]:
#define __cpp_lib_enable_string_view_conversion YYYYMML // also in <string_view> 
with the 
Modify [string.view.synop] as follows:
// [string.view.template], class template basic_string_view template < class charT , class traits = char_traits < charT >> class basic_string_view ; template < class T > constexpr bool enable_string_view_conversion = false; template < class T , class traits > constexpr bool enable_string_view_conversion_with_traits = false; template < class charT , class traits > constexpr bool enable_string_view_conversion < basic_string_view < charT , traits >> = true; template < class charT , class traits > constexpr bool enable_string_view_conversion_with_traits < basic_string_view < charT , traits > , traits > = true; 
Add a new section after [string.view.literals]:
23.4 Enablers for implicit string view construction from ranges [string.view.range.construction]1. Remarks: Pursuant to [namespace.std], users may specializetemplate < class T > constexpr bool enable_string_view_conversion = false; template < class T , class traits > constexpr bool enable_string_view_conversion_with_traits = false; andenable_string_view_conversion for cv-unqualified program-defined types. Such specializations shall be usable in constant expressions ([expr.const]) and have typeenable_string_view_conversion_with_traits .const bool 
Modify [string.syn] as follows:
// [basic.string], basic_string template < class charT , class traits = char_traits < charT > , class Allocator = allocator < charT >> class basic_string ; template < class charT , class traits , class Allocator > constexpr bool enable_string_view_conversion < basic_string < charT , traits , Allocator >> = true; template < class charT , class traits , class Allocator > constexpr bool enable_string_view_conversion_with_traits < basic_string < charT , traits , Allocator > , traits > = true; 
Modify [string.view.template.general] as shown:
template < class R > constexpr explicit ( see below ) basic_string_view ( R && r ); 
Modify [string.view.cons] as shown:
template < class R > constexpr explicit ( see below ) basic_string_view ( R && r ); 
Let
be an lvalue of typed .remove_cvref_t < R > 
Constraints:
(12.1) —
is not the same type asremove_cvref_t < R > ,basic_string_view (12.2) —
modelsR andranges :: contiguous_range ,ranges :: sized_range (12.3) —
isis_same_v < ranges :: range_value_t < R > , charT > true,(12.4) —
isis_convertible_v < R , const charT *> false, and(12.5) —
is not a valid expression.d . operator :: std :: basic_string_view < charT , traits > () 15. Remarks: The expression inside
Effects: Initializes
 withdata_ andranges :: data ( r )  withsize_ .ranges :: size ( r ) 
Throws: Any exception thrown by
andranges :: data ( r ) .ranges :: size ( r ) is equivalent toexplicit .! enable_string_view_conversion_with_traits < remove_cvref_t < R > , traits > 
6.2. Option 2: use a compatible inner type_traits 
   Modify [string.view.template.general] as shown:
template < class R > constexpr explicit ( see below ) basic_string_view ( R && r ); 
Modify [string.view.cons] as shown:
template < class R > constexpr explicit ( see below ) basic_string_view ( R && r ); 
Let
be an lvalue of typed .remove_cvref_t < R > 
Constraints:
(12.1) —
is not the same type asremove_cvref_t < R > ,basic_string_view (12.2) —
modelsR andranges :: contiguous_range ,ranges :: sized_range (12.3) —
isis_same_v < ranges :: range_value_t < R > , charT > true,(12.4) —
isis_convertible_v < R , const charT *> false, and(12.5) —
is not a valid expression.d . operator :: std :: basic_string_view < charT , traits > () 15. Remarks: If the qualified-id
Effects: Initializes
 withdata_ andranges :: data ( r )  withsize_ .ranges :: size ( r ) 
Throws: Any exception thrown by
andranges :: data ( r ) .ranges :: size ( r ) is valid, denotes a type, andremove_reference_t < R >:: traits_type isis_same_v < remove_reference_t < R >:: traits_type , traits > true, then the expression insideis equivalent toexplicit false. Otherwise, it is equivalent totrue.
Appendix A: traits_type 
boost / asio / basic_deadline_timer . hpp : 148 : typedef TimeTraits traits_type ; boost / asio / basic_waitable_timer . hpp : 170 : typedef WaitTraits traits_type ; boost / asio / experimental / basic_channel . hpp : 137 : typedef typename Traits :: template rebind < Signatures ... >:: other traits_type ; boost / asio / experimental / basic_concurrent_channel . hpp : 137 : typedef typename Traits :: template rebind < Signatures ... >:: other traits_type ; boost / asio / experimental / detail / channel_service . hpp : 299 : typedef typename Traits :: template rebind < Signatures ... >:: other traits_type ; boost / asio / experimental / detail / channel_service . hpp : 396 : typedef typename Traits :: template rebind < R () >:: other traits_type ; boost / asio / experimental / detail / channel_service . hpp : 499 : traits_type ; boost / asio / experimental / detail / impl / channel_service . hpp : 196 : Signatures ... >:: traits_type traits_type ; boost / asio / experimental / detail / impl / channel_service . hpp : 224 : Signatures ... >:: traits_type traits_type ; boost / asio / experimental / detail / impl / channel_service . hpp : 260 : Signatures ... >:: traits_type traits_type ; boost / asio / experimental / detail / impl / channel_service . hpp : 546 : Signatures ... >:: traits_type traits_type ; boost / beast / core / detail / ostream . hpp : 122 : using traits_type = typename boost / beast / core / detail / ostream . hpp : 51 : using traits_type = typename boost / beast / core / detail / static_ostream . hpp : 30 : using traits_type = typename boost / compute / container / basic_string . hpp : 46 : typedef Traits traits_type ; boost / container / string . hpp : 618 : typedef Traits traits_type ; boost / context / fixedsize_stack . hpp : 44 : typedef traitsT traits_type ; boost / context / pooled_fixedsize_stack . hpp : 127 : typedef traitsT traits_type ; boost / context / posix / protected_fixedsize_stack . hpp : 46 : typedef traitsT traits_type ; boost / context / posix / segmented_stack . hpp : 46 : typedef traitsT traits_type ; boost / context / windows / protected_fixedsize_stack . hpp : 38 : typedef traitsT traits_type ; boost / core / detail / string_view . hpp : 350 : typedef std :: char_traits < Ch > traits_type ; boost / coroutine / posix / protected_stack_allocator . hpp : 42 : typedef traitsT traits_type ; boost / coroutine / posix / segmented_stack_allocator . hpp : 43 : typedef traitsT traits_type ; boost / coroutine / standard_stack_allocator . hpp : 41 : typedef traitsT traits_type ; boost / coroutine / windows / protected_stack_allocator . hpp : 35 : typedef traitsT traits_type ; boost / date_time / date . hpp : 62 : typedef typename calendar :: date_traits_type traits_type ; boost / date_time / date_parsing . hpp : 145 : typedef typename std :: basic_string < char >:: traits_type traits_type ; boost / date_time / date_parsing . hpp : 314 : typedef typename std :: basic_string < charT >:: traits_type traits_type ; boost / date_time / time_duration . hpp : 285 : typedef typename base_duration :: traits_type traits_type ; boost / date_time / time_duration . hpp : 50 : typedef rep_type traits_type ; boost / date_time / time_parsing . hpp : 57 : typedef typename std :: basic_string < char_type >:: traits_type traits_type ; boost / fiber / future / packaged_task . hpp : 58 : > traits_type ; boost / fiber / future / promise . hpp : 40 : typedef std :: allocator_traits < typename object_type :: allocator_type > traits_type ; boost / format / alt_sstream . hpp : 47 : typedef Tr traits_type ; boost / geometry / srs / projections / impl / pj_ell_set . hpp : 179 : typedef srs :: spar :: detail :: ellps_traits < param_type > traits_type ; boost / geometry / srs / projections / spar . hpp : 1004 : typedef proj_traits < proj_type > traits_type ; boost / geometry / srs / projections / spar . hpp : 1021 : typedef proj_traits < typename o_proj_type :: type > traits_type ; boost / graph / distributed / adjacency_list . hpp : 1308 : traits_type ; boost / graph / vertex_and_edge_range . hpp : 24 : typedef graph_traits < Graph > traits_type ; boost / histogram / ostream . hpp : 46 : using traits_type = typename OStream :: traits_type ; boost / interprocess / streams / bufferstream . hpp : 274 : typedef typename std :: basic_ios < char_type , CharTraits >:: traits_type traits_type ; boost / interprocess / streams / bufferstream . hpp : 345 : typedef typename std :: basic_ios < char_type , CharTraits >:: traits_type traits_type ; boost / interprocess / streams / bufferstream . hpp : 417 : typedef typename std :: basic_ios < char_type , CharTraits >:: traits_type traits_type ; boost / interprocess / streams / bufferstream . hpp : 72 : typedef CharTraits traits_type ; boost / interprocess / streams / vectorstream . hpp : 388 : typedef typename std :: basic_ios < char_type , CharTraits >:: traits_type traits_type ; boost / interprocess / streams / vectorstream . hpp : 469 : typedef typename std :: basic_ios < char_type , CharTraits >:: traits_type traits_type ; boost / interprocess / streams / vectorstream . hpp : 544 : typedef typename std :: basic_ios < char_type , CharTraits >:: traits_type traits_type ; boost / interprocess / streams / vectorstream . hpp : 76 : typedef CharTraits traits_type ; boost / io / ostream_joiner . hpp : 48 : typedef Traits traits_type ; boost / iostreams / chain . hpp : 422 : typedef Tr traits_type ; \boost / iostreams / chain . hpp : 450 : typedef typename chain_type :: traits_type traits_type ; boost / iostreams / detail / buffer . hpp : 87 : typedef iostreams :: char_traits < Ch > traits_type ; boost / iostreams / detail / double_object . hpp : 101 : typedef boost :: call_traits < T > traits_type ; boost / iostreams / detail / double_object . hpp : 36 : typedef Metrowerks :: call_traits < T > traits_type ; boost / iostreams / detail / double_object . hpp : 38 : typedef boost :: call_traits < T > traits_type ; boost / iostreams / detail / double_object . hpp : 59 : typedef Metrowerks :: call_traits < T > traits_type ; boost / iostreams / detail / double_object . hpp : 61 : typedef boost :: call_traits < T > traits_type ; boost / iostreams / detail / double_object . hpp : 99 : typedef Metrowerks :: call_traits < T > traits_type ; boost / iostreams / filter / grep . hpp : 50 : typedef char_traits < char_type > traits_type ; boost / iostreams / filter / gzip . hpp : 463 : typedef char_traits < char > traits_type ; boost / iostreams / filter / line . hpp : 46 : typedef char_traits < char_type > traits_type ; boost / iostreams / filter / stdio . hpp : 52 : typedef BOOST_IOSTREAMS_CHAR_TRAITS ( Ch ) traits_type ; boost / iostreams / filter / symmetric . hpp : 76 : typedef BOOST_IOSTREAMS_CHAR_TRAITS ( char_type ) traits_type ; boost / iostreams / invert . hpp : 53 : typedef char_traits < char_type > traits_type ; boost / iostreams / read . hpp : 120 : typedef BOOST_IOSTREAMS_CHAR_TRAITS ( char_type ) traits_type ; boost / iostreams / read . hpp : 133 : typedef iostreams :: char_traits < char_type > traits_type ; boost / iostreams / read . hpp : 157 : typedef iostreams :: char_traits < char_type > traits_type ; boost / iostreams / read . hpp : 169 : typedef iostreams :: char_traits < char_type > traits_type ; boost / iostreams / read . hpp : 222 : typedef iostreams :: char_traits < char_type > traits_type ; boost / iostreams / skip . hpp : 40 : typedef iostreams :: char_traits < char_type > traits_type ; boost / iostreams / stream . hpp : 31 : typedef Tr traits_type ; boost / iostreams / traits . hpp : 277 : > traits_type ; boost / iostreams / traits . hpp : 353 : typedef Tr traits_type ; \boost / iostreams / write . hpp : 81 : typedef BOOST_IOSTREAMS_CHAR_TRAITS ( char_type ) traits_type ; boost / iostreams / write . hpp : 98 : typedef BOOST_IOSTREAMS_CHAR_TRAITS ( char_type ) traits_type ; boost / lexical_cast / lexical_cast_old . hpp : 98 : typedef Traits traits_type ; boost / log / detail / attachable_sstream_buf . hpp : 61 : typedef typename base_type :: traits_type traits_type ; boost / log / expressions / formatter . hpp : 59 : typedef typename StreamT :: traits_type traits_type ; boost / log / expressions / formatters / c_decorator . hpp : 134 : typedef c_decorator_traits < char_type > traits_type ; boost / log / expressions / formatters / c_decorator . hpp : 194 : typedef aux :: c_decorator_traits < char_type > traits_type ; boost / log / expressions / formatters / csv_decorator . hpp : 93 : typedef csv_decorator_traits < char_type > traits_type ; boost / log / expressions / formatters / xml_decorator . hpp : 92 : typedef xml_decorator_traits < char_type > traits_type ; boost / log / sources / record_ostream . hpp : 98 : typedef typename base_type :: traits_type traits_type ; boost / log / support / date_time . hpp : 70 : typedef typename TimeDurationT :: traits_type traits_type ; boost / log / utility / formatting_ostream . hpp : 127 : typedef TraitsT traits_type ; boost / log / utility / string_literal . hpp : 58 : typedef TraitsT traits_type ; boost / numeric / interval / interval . hpp : 45 : typedef Policies traits_type ; boost / polygon / polygon_90_set_traits . hpp : 56 : typedef typename traits_by_concept < T , T2 >:: type traits_type ; boost / polygon / polygon_90_set_traits . hpp : 62 : typedef typename traits_by_concept < T , T2 >:: type traits_type ; boost / process / detail / posix / basic_pipe . hpp : 34 : typedef Traits traits_type ; boost / process / detail / windows / basic_pipe . hpp : 31 : typedef Traits traits_type ; boost / process / pipe . hpp : 105 : typedef Traits traits_type ; boost / process / pipe . hpp : 306 : typedef Traits traits_type ; boost / process / pipe . hpp : 40 : typedef Traits traits_type ; boost / process / pipe . hpp : 417 : typedef Traits traits_type ; boost / process / pipe . hpp : 526 : typedef Traits traits_type ; boost / process / v2 / cstring_ref . hpp : 55 : using traits_type = Traits ; boost / process / v2 / environment . hpp : 117 : using traits_type = key_char_traits < char_type > ; boost / process / v2 / environment . hpp : 208 : using traits_type = value_char_traits < char_type > ; boost / process / v2 / environment . hpp : 303 : using traits_type = std :: char_traits < char_type > ; boost / process / v2 / environment . hpp : 487 : using traits_type = key_char_traits < char_type > ; boost / process / v2 / environment . hpp : 707 : using traits_type = value_char_traits < char_type > ; boost / process / v2 / environment . hpp : 934 : using traits_type = std :: char_traits < char_type > ; boost / range / detail / collection_traits_detail . hpp : 288 : typedef array_traits < T > traits_type ; boost / regex / concepts . hpp : 301 : typedef typename regex_traits_computer < Regex >:: type traits_type ; boost / regex / v4 / basic_regex . hpp : 333 : typedef traits traits_type ; boost / regex / v4 / match_results . hpp : 384 : typedef :: boost :: regex_traits_wrapper < typename RegexT :: traits_type > traits_type ; boost / regex / v4 / match_results . hpp : 396 : typedef :: boost :: regex_traits_wrapper < typename RegexT :: traits_type > traits_type ; boost / regex / v5 / basic_regex . hpp : 322 : typedef traits traits_type ; boost / regex / v5 / match_results . hpp : 355 : typedef :: boost :: regex_traits_wrapper < typename RegexT :: traits_type > traits_type ; boost / regex / v5 / match_results . hpp : 367 : typedef :: boost :: regex_traits_wrapper < typename RegexT :: traits_type > traits_type ; boost / spirit / home / karma / stream / ostream_iterator . hpp : 36 : typedef Traits traits_type ; boost / static_string / static_string . hpp : 833 : using traits_type = Traits ; boost / test / utils / basic_cstring / basic_cstring . hpp : 50 : typedef ut_detail :: bcs_char_traits < CharT > traits_type ; boost / test / utils / basic_cstring / basic_cstring . hpp : 622 : typedef typename basic_cstring < CharT1 >:: traits_type traits_type ; boost / test / utils / basic_cstring / compare . hpp : 105 : typedef typename boost :: unit_test :: basic_cstring < CharT >:: traits_type traits_type ; boost / test / utils / nullstream . hpp : 46 : typedef typename base_type :: traits_type traits_type ; boost / url / grammar / string_view_base . hpp : 86 : typedef std :: char_traits < char > traits_type ; boost / utility / string_view . hpp : 58 : typedef traits traits_type ; boost / wave / util / flex_string . hpp : 1445 : typedef T traits_type ; boost / wave / util / flex_string . hpp : 2381 : typedef typename flex_string < E , T , A , S >:: traits_type traits_type ; boost / xpressive / detail / core / linker . hpp : 117 : typedef typename regex_traits_type < Locale , BidiIter >:: type traits_type ; boost / xpressive / detail / core / matcher / charset_matcher . hpp : 31 : typedef Traits traits_type ; boost / xpressive / detail / core / matcher / posix_charset_matcher . hpp : 33 : typedef Traits traits_type ; boost / xpressive / detail / static / compile . hpp : 77 : typedef typename default_regex_traits < char_type >:: type traits_type ; boost / xpressive / detail / static / compile . hpp : 90 : typedef typename regex_traits_type < locale_type , BidiIter >:: type traits_type ; boost / xpressive / detail / static / transforms / as_set . hpp : 107 : typedef typename Data :: traits_type traits_type ; boost / xpressive / detail / static / visitor . hpp : 108 : typedef Traits traits_type ; boost / xpressive / detail / utility / boyer_moore . hpp : 42 : typedef Traits traits_type ; boost / xpressive / detail / utility / chset / chset . hpp : 34 : typedef Traits traits_type ; boost / xpressive / regex_compiler . hpp : 59 : typedef RegexTraits traits_type ; 
7. Acknowledgements
Thanks to KDAB for supporting this work.
All remaining errors are ours and ours only.