string_ref
: a non-owning reference to a string, revision 2This paper updates N3334
(string_ref
+ array_ref
) and N3442
(string_ref
for a TS) with wording for the draft
C++14 standard. Note that we still aren't sure whether we're aiming for
a TS or C++14. The most
recent version of this paper is maintained on GitHub.
References to strings are very common in C++ programs, but often the callee doesn't care about the exact type of the object that owns the data. 3 things generally happen in this case:
const std::string&
and insists
that callers copy the data if it was originally owned by another
type.char*
and
a length (or just char*
and assumes
0-termination)—and reduces the readability and safety of
calls and loses any helper functions the original type
provided.Google, LLVM, and Bloomberg have independently implemented a
string-reference type to encapsulate this kind of argument. string_ref
is implicitly
constructible from const char*
and std::string
. It
provides most of the const
member operations from
std::string
to ease conversion. This paper follows Chromium
and Bloomberg
in extending string_ref
to basic_string_ref<charT>
, and
further extends it to include a traits
parameter to match
basic_string
. We provide typedefs to parallel the 4
basic_string
typedefs.
Both Google's and LLVM's string_ref
types (but not
Bloomberg's) extend the interface from std::string
to provide
some helpful utility functions:
Versions of std::string
operations that take
string_ref
instead also give the standard a way to provide
in-place operations on non-null-terminated byte/character sequences:
Google's StringPiece
provides as_string
and
ToString
methods to convert to std::string
. LLVM's
StringRef
provides both a str()
explicit
conversion and an implicit operator std::string()
. Since this
paper builds on top of C++11, we provide an explicit
conversion
constructor as well as a less verbose to_string
function.
Google's and LLVM's string_ref
types provide a subset of
std::string
's searching operations, but they do provide
pos
arguments to specify where to start the search. Because string_ref::substr
is
much cheaper than string::substr
, this paper removes the
pos
argument entirely.
None of the existing classes have constexpr
methods.
Consensus
seems to be developing around renaming this class to
string_view
. If that keeps up, the next revision of this
paper will incorporate that change. Other options include:
The interface of string_ref
is similar to, but not exactly
the same as the interface of std::string
. In general, we want
to minimize differences between std::string
and
string_ref
so that users can go back and forth between the two
often. This section justifies the differences whose utility we think
overcomes that general rule.
remove_prefix()
and
remove_suffix()
make
it easy to parse strings using string_ref
. They could both
be implemented as non-member functions (e.g. str.remove_prefix(n)
=== str = str.substr(n)
), but it seems useful to
provide the simplest mutators as member functions. Note that other
traversal primitives need to be non-members so that they're
extensible, which may argue for pulling these out too.starts_with(haystack, needle)
vs
starts_with(needle, haystack)
, while
haystack.starts_with(needle)
is the only English reading of
the member version. These queries apply equally well to
basic_string
, so I've added them there too.copy
method has been removed from
string_ref
. std::string::copy
is copy
out, not in. It's not well named. Users can easily use
std::copy
instead.pos
and n
parameters to methods have been
removed from string_ref
. std::string
needs
these parameters because std::string::substring
is an
expensive (copying and sometimes allocating) operation. However, these
are always integral parameters, so the compiler can't check that their
order is correct, and readers often have a hard time. Because string_ref::substr
is cheap,
we insist users call it instead of passing its arguments to other
functions.This paper makes
char_traits::
{length
,find
,compare
}
constexpr
so that basic_string_ref
can be
constructed from string literals at compile time and so that
basic_string_ref::
{find
,compare
,operator==
,
etc.} can be constexpr
. This implements the proposed
resolution for LWG Issue
2232. An alternate way to get compile-time string_ref
s
would be to define a user-defined literal operator a'la N3468. Arguably,
basic_string_ref
is a better candidate for the ""s
suffix than basic_string
since basic_string
isn't
a literal type.
When deciding which functions to add basic_string_ref
overloads to, I followed the following rules:
const char*
and
basic_string
, I added a basic_string_ref
overload.basic_string
overload but not a
const char*
overload, and const char*
arguments
could not be passed with an implicit conversion (generally because
template argument deduction would fail), I added a
basic_string_ref
overload.basic_string
overload but not a
const char*
overload, and const char*
arguments
could be passed with an implicit conversion, then I did not add a
basic_string_ref
overload, on the theory that copies are
already expected and cheap enough, and because adding a
basic_string_ref
overload would require also adding a
const char*
overload to avoid breaking user code.I didn't add basic_string_ref
overloads to a few functions
where this would be hard to implement:
_byname
facets are implemented on Unix by forwarding
to a C library function that takes a '\0'
-terminated string,
with no option to pass a length. Since accepting a
string_ref
would require a copy regardless, users may as well
pass a string
.basic_string
, and
forward the argument on to a virtual method. Defining a version taking
basic_string_ref
, even with a default implementation
forwarding to the string
version, would break user subclasses
because of a common compiler warning that fires when a virtual method is
hidden. This propagates to the put_money
I/O manipulator.I also omitted operator+(basic_string, basic_string_ref)
because LLVM returns a lightweight object from this overload and only
performs the concatenation lazily. If we define this overload, we'll have a
hard time introducing that lightweight concatenation later.
Following the basic_string
and const
char*
overloads of regex_replace()
, the
string_ref
overloads don't let the user specify an explicit
allocator. This should be fixed with the resolution to issue 2216.
I believe you have enough to read in this paper as it is and that it would
be unwise to jam a fix into here.
I haven't taken every suggestion to change string_ref
. This
section explains the rationales.
Many people have asked why we aren't removing all of the
find*
methods, since they're widely considered a
wart on std::string
. First, we'd like to make it as easy as
possible to convert code to use string_ref
, so it's useful to
keep the interface as similar as reasonable to std::string
.
Second, replacing these these methods with uses of the standard algorithms
library requires switching from indices to iterators, writing
somewhat-complicated conversion code, and/or passing custom lambdas to
find_if
. Let's look at the replacement code for each of the
remaining methods:
haystack.find(needle)
auto iter = std::search(haystack.begin(), haystack.end(),
needle.begin(), needle.end());
return iter == haystack.end() ? std::string::npos : iter - haystack.begin();
haystack.rfind(needle)
auto iter = std::find_end(haystack.begin(), haystack.end(),
needle.begin(), needle.end());
return iter == haystack.end() ? std::string::npos : iter - haystack.begin();
haystack.find_first_of(needles)
auto iter = std::find_first_of(haystack.begin(), haystack.end(),
needles.begin(), needles.end());
return iter == haystack.end() ? std::string::npos : iter - haystack.begin();
haystack.find_last_of(needles)
auto iter = std::find_first_of(haystack.rbegin(), haystack.rend(),
needles.begin(), needles.end());
return iter == haystack.rend() ? std::string::npos : iter.base() - 1 - haystack.begin();
haystack.find_first_not_of(straw)
auto iter = std::find_if(haystack.begin(), haystack.end(), [&](char c) {
return std::find(straw.begin(), straw.end(), c) == straw.end();
});
return iter == haystack.end() ? std::string::npos : iter - haystack.begin();
haystack.find_last_not_of(straw)
auto iter = std::find_if(haystack.rbegin(), haystack.rend(), [&](char c) {
return std::find(straw.begin(), straw.end(), c) == straw.end();
});
return iter == haystack.rend() ? std::string::npos : iter.base() - 1 - haystack.begin();
find
, rfind
, and find_first_of
are straightforward, although the conversion from indices to iterators
would prevent many users from switching even to them.
find_last_of
, find_first_not_of
, and
find_last_not_of
get progressively worse to handle even in an
iterator-based function.
basic_string_ref<char>
mutable… and use basic_string_ref<const char>
for the constant
case. The constant case is enough more common than the mutable case that
it needs to be the default. Making the mutable case the default would
prevent passing string literals into string_ref
parameters,
which would defeat a significant use case for string_ref
. In
a somewhat analogous sitation, LLVM defined an ArrayRef
class in Feb 2011, and didn't find a need for the matching
MutableArrayRef
until Jan 2012. They still haven't needed a
mutable version of StringRef
.
One possible reason for this is that most uses that need to modify a
string also need to be able to change its length, and that's impossible
through even a mutable version of string_ref
.
We could use typedef basic_string_ref<const char>
string_ref
to make the immutable case the default while still
supporting the mutable case using the same template. I haven't gone this
way because it would complicate the template's definition without
significantly helping users.
explicit operator bool
This would be an abbreviation for !empty()
, usable for
initialization in if
statements. I didn't add this because
it would be inconsistent with the rest of the containers library, but if
another proposal adds it to the rest of the containers, that proposal
should also add it to string_ref
.
strlen("string literal")
With a constructor of the form:
template<size_t N>
basic_string_ref(const charT (&str)[N]);
we could avoid a strlen()
call when a
basic_string_ref
is constructed from a string literal.
Unfortunately, this constructor does completely the wrong thing when
called like:
char space[PATH_MAX];
snprintf(space, sizeof(space), "some string");
string_ref str(space);
I don't know any way to distinguish string literals from local arrays,
so the only way to be safe is to call strlen()
on array
arguments. Some people have suggested a
string_ref::from_literal
method, but I consider that too
verbose.
Even the original worry is obsolete given modern optimizers: both gcc
and clang optimize strlen("Literal")
into a constant, making
the safe code as efficient as the template. Other implementations should
provide the same optimization as a QoI issue.
begin
/end
instead of the elementsOperations on string_ref
apply to the characters in the
string, and not the pointers that refer to the characters. This
introduces the possibility that the underlying characters might change
while a string_ref
referring to them is in an associative
container, which would break the container, but we believe this risk is
worthwhile because it matches existing practice and matches user
intentions more often.
contiguous_range<charT>
contiguous_range<T>
along with an
is_contiguous<IteratorOrRange>
trait would be useful for
many purposes. However, a reference class that's specifically for strings
provides a couple extra benefits:
string_ref
can have an implicit conversion from
const char*
, while it would be a surprising special case to
provide that on contiguous_range<const char*>
.basic_string
's interface to
ease transitions to and from ownership, while such methods would be very
strange on contiguous_range
.basic_string_ref
takes a char_traits
argument allowing customization of comparison.
contiguous_range
likely wouldn't.string_ref
s using the elements they
refer to. There's a stronger argument to compare a
contiguous_range
using the pointers inside it, meaning two
contiguous_range<char>
s of the same characters might
compare unequal.std::string
in
addition to std::vector<char>
. Users benefit from
saying which they mean in interfaces.string_ref
null-terminatedDoing this naively makes substr
impossible to implement
without a copy. We could imagine inventing a more complex interface that
records whether the input string was null-terminated, giving the user the
option to use that string when trying to pass a string_ref
to
a legacy or C function expecting a null-terminated const
char*
. This proposal doesn't include such an interface because it
would make string_ref
bigger or more expensive, and because
there's no existing practice to guide us toward the right interface.
Another option would be to define a separate zstring_ref
class to represent null-terminated strings and let it decay to
string_ref
when necessary. That's plausible but not part of
this proposal.
In Kona
2012, I proposed a range<>
class with
pop_front
, etc. members that adjusted the bounds of the
range. Discussion there indicated that committee members were
uncomfortable using the same names for lightweight range operations as
container operations. Existing practice doesn't agree on a name for this
operation, so I've kept the name used by Google's
StringPiece
.
Beman
Dawes suggested defining std::string_ref_{begin,end}
and
allowing users to add overloads within std
. Using ADL is a
slight variant. We could also allow conversion from any type with
.data()
and .size()
members returning the right
types.
Ultimately, I think we want to allow this conversion based on detecting contiguous ranges. Any constructor we add to work around that is going to look like a wart in a couple years. I think we'll be better off making users explicitly convert when they can't add an appropriate conversion operator, and then we can add the optimal constructor when contiguous iterators make it into the library.
How does this interact with N3456?
Several basic_string_ref
overloads would be handled by the
Range&&
arguments that N3456 adds, and several more (e.g. in
<regex>
) would be handled by extending those template
arguments to the rest of the library. In non-deducing contexts,
basic_string_ref
can serve as an implicit conversion target, so we want it
anyway, but in deducing context, I think the Range&&
argument is strictly
better.
Wording changes are being maintained at https://github.com/google/cxx-std-draft/compare/string-ref and a snapshot of the changes is copied below. A very early implementation is at https://github.com/google/libcxx/compare/string-ref. Patches and pull requests are welcome against both.
For example, the class template templates
basic_string and basic_string_ref and the non-member
function templates that operate on strings are referred to as the
string component.
template<class charT, class traits>
explicit bitset(
basic_string_ref<charT,traits> str,
charT zero = charT(’0’), charT one = charT(’1’));
template <class charT, class traits, class Allocator>
explicit
bitset(const basic_string<charT, traits, Allocator>& str,
typename basic_string<charT, traits, Allocator>::size_type pos = 0,
typename basic_string<charT, traits, Allocator>::size_type n =
basic_string<charT, traits, Allocator>::npos,
charT zero = charT(’0’), charT one = charT(’1’));
Effects: Equivalent to bitset(basic_string_ref<charT, traits>(str).substr(pos, n),
zero, one)
template <class charT, class traits>
explicit
bitset(basic_string_ref<charT, traits> str,
charT zero = charT(’0’), charT one = charT(’1’));
Requires: pos <= str.size()
.
Throws: out_of_range
if pos > str.size()
.
Effects: Determines the effective length rlen
of the initializing string as the smaller of n
and str.size() - pos
.
The function then throws Throws:
invalid_argument
if any of the rlen characters in
str
beginning at position pos is other than zero or one. The function
uses traits::eq()
to compare the character values.
Otherwise, the Effects: function
constructs an object of class bitset<N>
, initializing
the first M
bit positions to values determined from the
corresponding characters in the string
str
. M
is the smaller of N
and
.rlenstr.size()
An element of the constructed string has value zero if the corresponding
character in str
, beginning at position pos, is 0
zero
. Otherwise, the element has the value 1. Character
position pos
corresponds to bit position
zero. Subsequent decreasing character positions correspond to increasing bit
positions.+ M - 1
If M < N
, remaining bit positions are initialized to zero.
template <class charT>
explicit bitset(
const charT* str,
typename basic_string<charT>::size_type n = basic_string<charT>::npos,
charT zero = charT(’0’), charT one = charT(’1’));
Effects: Constructs an object of class bitset<N> as if by
bitset(
n == basic_string<charT>::npos
? basic_string_ref<charT>(str)
: basic_string_ref<charT>(str, n),
0, n, zero, one)
This implements the proposed resolution of LWG issue ####. I could take it out at the cost of making
basic_string_ref(const charT*)
and all of the comparison
operators and methods non-constexpr
.
static constexpr int compare(const char_type* s1, const char_type* s2, size_t n);
static constexpr size_t length(const char_type* s);
static constexpr const char_type* find(const char_type* s, size_t n,
const char_type& a);
The header <string> defines the basic_string class template for manipulating varying-length sequences of char-like objects and four typedefs, string, u16string, u32string, and wstring, that name the specializations basic_string<char>, basic_string<char16_t>, basic_string<char32_t>, and basic_string<wchar_t>, respectively.
<string> also defines the basic_string_ref
class
template for referring to constant sequences of char-like objects and four
typedefs, string_ref
, u16string_ref
,
u32string_ref
, and wstring_ref
, that name the
specializations basic_string_ref<char>
,
basic_string_ref<char16_t>
,
basic_string_ref<char32_t>
, and
basic_string_ref<wchar_t>
, respectively.
// [basic.string.ref], basic_string_ref:
template<class charT, class traits = char_traits<charT>>
class basic_string_ref;
// [string.ref.comparison], non-member basic_string_ref comparison functions
template<typename charT, typename traits>
bool operator==(basic_string_ref<charT, traits> x, basic_string_ref<charT, traits> y);
template<typename charT, typename traits>
bool operator!=(basic_string_ref<charT, traits> x, basic_string_ref<charT, traits> y);
template<typename charT, typename traits>
bool operator< (basic_string_ref<charT, traits> x, basic_string_ref<charT, traits> y);
template<typename charT, typename traits>
bool operator> (basic_string_ref<charT, traits> x, basic_string_ref<charT, traits> y);
template<typename charT, typename traits>
bool operator<=(basic_string_ref<charT, traits> x, basic_string_ref<charT, traits> y);
template<typename charT, typename traits>
bool operator>=(basic_string_ref<charT, traits> x, basic_string_ref<charT, traits> y);
// Sufficient additional overloads to allow mixed comparisons with any type
// that has an implicit conversion to basic_string_ref<charT, traits>.
// [string.ref.nonmem], other non-member basic_string_ref functions
template<class charT, class traits = char_traits<charT>,
class Allocator = allocator<charT> >
basic_string<charT, traits, Allocator> to_string(
basic_string_ref<charT, traits>,
const Allocator& a = Allocator());
template<class charT, class traits>
basic_ostream<charT, traits>&
operator<<(basic_ostream<charT, traits>& os,
basic_string_ref<charT,traits> str);
// basic_string_ref typedef names
typedef basic_string_ref<char> string_ref;
typedef basic_string_ref<char16_t> u16string_ref;
typedef basic_string_ref<char32_t> u32string_ref;
typedef basic_string_ref<wchar_t> wstring_ref;
It would be nice to remove the string
overloads for the
numeric conversion functions, but that could break code that relies on an
implicit conversion to string. Instead, we need to add const
char*
overloads to avoid ambiguity.
I'd also like to add optional<T>
stox_consume(string_ref&, int base=10)
if/when
optional
becomes available.
int stoi(string_ref str, size_t* idx = 0, int base = 10);
int stoi(const char* str, size_t* idx = 0, int base = 10);
long stol(string_ref str, size_t* idx = 0, int base = 10);
long stol(const char* str, size_t* idx = 0, int base = 10);
unsigned long stoul(string_ref str, size_t* idx = 0, int base = 10);
unsigned long stoul(const char* str, size_t* idx = 0, int base = 10);
long long stoll(string_ref str, size_t* idx = 0, int base = 10);
long long stoll(const char* str, size_t* idx = 0, int base = 10);
unsigned long long stoull(string_ref str, size_t* idx = 0, int base = 10);
unsigned long long stoull(const char* str, size_t* idx = 0, int base = 10);
float stof(string_ref str, size_t* idx = 0);
float stof(const char* str, size_t* idx = 0);
double stod(string_ref str, size_t* idx = 0);
double stod(const char* str, size_t* idx = 0);
long double stold(string_ref str, size_t* idx = 0);
long double stold(const char* str, size_t* idx = 0);
int stoi(wstring_ref str, size_t* idx = 0, int base = 10);
int stoi(const wchar_t* str, size_t* idx = 0, int base = 10);
long stol(wstring_ref str, size_t* idx = 0, int base = 10);
long stol(const wchar_t* str, size_t* idx = 0, int base = 10);
unsigned long stoul(wstring_ref str, size_t* idx = 0, int base = 10);
unsigned long stoul(const wchar_t* str, size_t* idx = 0, int base = 10);
long long stoll(wstring_ref str, size_t* idx = 0, int base = 10);
long long stoll(const wchar_t* str, size_t* idx = 0, int base = 10);
unsigned long long stoull(wstring_ref str, size_t* idx = 0, int base = 10);
unsigned long long stoull(const wchar_t* str, size_t* idx = 0, int base = 10);
float stof(wstring_ref str, size_t* idx = 0);
float stof(const wchar_t* str, size_t* idx = 0);
double stod(wstring_ref str, size_t* idx = 0);
double stod(const wchar_t* str, size_t* idx = 0);
long double stold(wstring_ref str, size_t* idx = 0);
long double stold(const wchar_t* str, size_t* idx = 0);
template <> struct hash<string_ref>;
template <> struct hash<u16string_ref>;
template <> struct hash<u32string_ref>;
template <> struct hash<wstring_ref>;
The class template basic_string_ref describes objects that can refer to a constant sequence of arbitrary char-like objects with the first element of the sequence at position zero. In the rest of this Clause, the type of the char-like objects held in a basic_string_ref object is designated by charT.
[Note: The library provides implicit conversions from const charT* and std::basic_string<charT, ...> to std::basic_string_ref<charT, ...> so that user code can accept just std::basic_string_ref<charT> as a parameter wherever a sequence of characters is expected. User-defined types should define their own implicit conversions to std::basic_string_ref in order to interoperate with these functions. — end note ]
The complexity of member functions is O(1) unless otherwise specified.
namespace std {
template<typename charT, typename traits = char_traits<charT>>
class basic_string_ref {
public:
// types
typedef charT value_type;
typedef const charT* pointer;
typedef const charT* const_pointer;
typedef const charT& reference;
typedef const charT& const_reference;
typedef implementation-defined const_iterator; // See [string.ref.iterators]
typedef const_iterator iterator; // [Footnote: Because basic_string_ref refers to a constant sequence, iterator and const_iterator are the same type. --end footnote]
typedef std::reverse_iterator<const_iterator> const_reverse_iterator; typedef const_reverse_iterator reverse_iterator;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
static constexpr size_type npos = size_type(-1);
// [string.ref.cons], construct/copy
constexpr basic_string_ref() noexcept;
constexpr basic_string_ref(const basic_string_ref&) noexcept = default;
basic_string_ref& operator=(const basic_string_ref&) noexcept = default;
constexpr basic_string_ref(const charT* str);
constexpr basic_string_ref(const charT* str, size_type len);
No initializer_list constructor because [dcl.init.list]p6 says it would likely store a dangling reference into the string_ref.
// [string.ref.iterators], iterators
constexpr const_iterator begin() const noexcept;
constexpr const_iterator end() const noexcept;
constexpr const_iterator cbegin() const noexcept;
constexpr const_iterator cend() const noexcept;
reverse_iterator methods aren’t constexpr because reverse_iterator isn’t a literal type. See LWG Issue 2208.
const_reverse_iterator rbegin() const noexcept;
const_reverse_iterator rend() const noexcept;
const_reverse_iterator crbegin() const noexcept;
const_reverse_iterator crend() const noexcept;
// [string.ref.capacity], capacity
constexpr size_type size() const noexcept;
constexpr size_type length() const noexcept;
constexpr size_type max_size() const noexcept;
constexpr bool empty() const noexcept;
// [string.ref.access], element access
constexpr const charT& operator[](size_type pos) const;
const charT& at(size_t pos) const;
constexpr const charT& front() const;
constexpr const charT& back() const;
constexpr const charT* data() const noexcept;
// [string.ref.modifiers], modifiers:
void clear() noexcept;
void remove_prefix(size_type n);
void remove_suffix(size_type n);
// [string.ref.ops], string operations:
constexpr basic_string_ref substr(size_type pos, size_type n=npos) const;
constexpr int compare(basic_string_ref s) const noexcept;
constexpr int compare(const charT* s) const noexcept;
constexpr bool starts_with(basic_string_ref s) const noexcept;
constexpr bool starts_with(charT c) const noexcept;
constexpr bool starts_with(const charT* s) const noexcept;
constexpr bool ends_with(basic_string_ref s) const noexcept;
constexpr bool ends_with(charT c) const noexcept;
constexpr bool ends_with(const charT* s) const noexcept;
size_type find(basic_string_ref s) const noexcept;
size_type find(charT c) const noexcept;
size_type find(const charT* s) const noexcept;
size_type rfind(basic_string_ref s) const noexcept;
size_type rfind(charT c) const noexcept;
size_type rfind(const charT* s) const noexcept;
size_type find_first_of(basic_string_ref s) const noexcept;
size_type find_first_of(charT c) const noexcept;
size_type find_first_of(const charT* s) const noexcept;
size_type find_last_of(basic_string_ref s) const noexcept;
size_type find_last_of(charT c) const noexcept;
size_type find_last_of(const charT* s) const noexcept;
size_type find_first_not_of(basic_string_ref s) const noexcept;
size_type find_first_not_of(charT c) const noexcept;
size_type find_first_not_of(const charT* s) const noexcept;
size_type find_last_not_of(basic_string_ref s) const noexcept;
size_type find_last_not_of(charT c) const noexcept;
size_type find_last_not_of(const charT* s) const noexcept;
};
Each member function of the form
rt fx1(const charT* s); // such as compare(), find()
is equivalent to fx1(basic_string_ref(s))
.
Each member function of the form
rt fx2(charT c); // such as starts_with(), find()
is equivalent to fx2(basic_string_ref(&c, 1))
.
constexpr basic_string_ref();
Effects: Constructs an empty basic_string_ref.
Postcondition: empty() == true and [data(),data()) is a valid range.
basic_string_ref(const charT* str);
Requires: [str,str + traits::length(str)) is a valid range.
Effects: Constructs a basic_string_ref referring to the same string as str, with the postconditions in Table [tab:string.ref.ctr.1]
Element | Value |
---|---|
data() | str |
size() | traits::length(str) |
Complexity: O(size())
constexpr basic_string_ref(const charT* str, size_type len);
Requires: str is not a null pointer and [str,str + len) is a valid range.
Effects: Constructs a basic_string_ref, with the postconditions in Table [tab:string.ref.ctr.2]
Element | Value |
---|---|
data() | str |
size() | len |
typedef implementation-defined const_iterator;
A random-access, contiguous iterator type.
For a basic_string_ref str, any operation that invalidates a pointer in the range [str.data(), str.data()+str.size()) invalidates pointers and iterators returned from str’s methods.
constexpr const_iterator begin() const noexcept;
constexpr const_iterator cbegin() const noexcept;
Returns: An iterator referring to the first character in the string.
constexpr const_iterator end() const noexcept;
constexpr const_iterator cend() const noexcept;
Returns: An iterator which is the past-the-end value.
const_reverse_iterator rbegin() const noexcept;
const_reverse_iterator crbegin() const noexcept;
Returns: An iterator which is semantically equivalent to reverse_iterator(end()).
const_reverse_iterator rend() const noexcept;
const_reverse_iterator crend() const noexcept;
Returns: An iterator which is semantically equivalent to reverse_iterator(begin()).
size_type size() const noexcept;
Returns: A count of the number of char-like objects referred to by the string_ref.
Complexity: constant time.
size_type length() const noexcept;
Returns: size().
size_type max_size() const noexcept;
Returns: The size of the largest possible string_ref.
bool empty() const noexcept;
Returns: size() == 0.
constexpr const_reference operator[](size_type pos) const;
Requires: pos < size().
Returns: *(begin() + pos)
Throws: Nothing.
[ Note: Unlike basic_string::operator[], basic_string_ref::operator[](size()) has undefined behavior instead of returning charT(). — end note ]
constexpr const_reference at(size_type pos) const;
Throws: out_of_range if pos >= size().
Returns: operator[](pos).
constexpr const charT& front() const;
Requires: !empty()
Effects: Equivalent to operator[](0).
constexpr const charT& back() const;
Requires: !empty()
Effects: Equivalent to operator[](size() - 1).
const charT* data() const noexcept;
Returns: A non-null pointer p such that p + i == &operator[](i) for each i in [0,size()).
[ Note: Unlike std::string::data() and string literals, data() may return a pointer to a buffer that is not null-terminated. Therefore it is typically a mistake to pass data() to a routine that takes just a const charT* and expects a null-terminated string. — end note ]
void clear() noexcept;
Effects: Equivalent to *this = basic_string_ref()
void remove_prefix(size_type n);
Requires: n <= size()
Effects: Equivalent to *this = substr(n, npos)
void remove_suffix(size_type n);
Requires: n <= size()
Effects: Equivalent to *this = substr(0, size() - n)
[ Note: Unlike std::basic_string, std::basic_string_ref provides no whole-string methods with posi- tion or length parameters. Instead, users should use the substr() method to create the character sequence they’re actually interested in, and use that. — end note ]
basic_string_ref substr(size_type pos, size_type n = npos) const;
Throws: out_of_range if pos > size().
Effects: Determines the effective length rlen of the string to reference as the smaller of n and size() - pos.
Returns: basic_string_ref(data()+pos, rlen).
int compare(const basic_string_ref& str) const noexcept;
Effects: Determines the effective length rlen of the strings to compare as the smallest of size() and str.size(). The function then compares the two strings by calling traits::compare(data(), str.data(), rlen).
Complexity: O(rlen)
Returns: The nonzero result if the result of the comparison is nonzero. Otherwise, returns a value as indicated in Table [tab:string.ref.compare].
Condition | Return Value |
---|---|
size() < str.size() | < 0 |
size() == str.size() | 0 |
size() > str.size() | > 0 |
bool starts_with(const basic_string_ref& prefix) const noexcept;
Complexity: O(min(size(), prefix.size()))
Returns: size() >= prefix.size() &&
bool ends_with(const basic_string_ref& suffix) const noexcept;
Complexity: O(min(size(), suffix.size()))
Returns: size() >= suffix.size() &&
Member functions in this section have complexity O(size() * argument.size()) at worst, although implementations are encouraged to do better.
size_type find(const basic_string_ref& str) const noexcept;
Effects: Determines the lowest position xpos, if possible, such that both of the following conditions obtain:
Returns: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
Remarks: Uses traits::eq().
size_type rfind(const basic_string_ref& str) const noexcept;
Effects: Determines the highest position xpos, if possible, such that both of the following conditions obtain:
Returns: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
Remarks: Uses traits::eq().
size_type find_first_of(const basic_string_ref& str) const noexcept;
Effects: Determines the lowest position xpos, if possible, such that both of the following conditions obtain:
Returns: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
Remarks: Uses traits::eq().
size_type find_last_of(const basic_string_ref& str) const noexcept;
Effects: Determines the highest position xpos, if possible, such that both of the following conditions obtain:
Returns: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
Remarks: Uses traits::eq().
size_type find_first_not_of(const basic_string_ref& str) const noexcept;
Effects: Determines the lowest position xpos, if possible, such that both of the following conditions obtain:
Returns: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
Remarks: Uses traits::eq().
size_type find_last_not_of(const basic_string_ref& str) const noexcept;
Effects: Determines the highest position xpos, if possible, such that both of the following conditions obtain:
Returns: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
Remarks: Uses traits::eq().
Implementations shall provide sufficient additional overloads so that an
object t
with an implicit conversion to
basic_string_ref<charT, traits>
can be compared according to
Table [tab:string.ref.comparison.overloads], where
sp
is an instance of
basic_string_ref<charT, traits>
.
Expression | Equivalent to |
---|---|
t == sp | basic_string_ref<charT, traits>(t) == sp |
sp == t | sp == basic_string_ref<charT, traits>(t) |
t != sp | basic_string_ref<charT, traits>(t) != sp |
sp != t | sp != basic_string_ref<charT, traits>(t) |
t < sp | basic_string_ref<charT, traits>(t) < sp |
sp < t | sp < basic_string_ref<charT, traits>(t) |
t > sp | basic_string_ref<charT, traits>(t) > sp |
sp > t | sp > basic_string_ref<charT, traits>(t) |
t <= sp | basic_string_ref<charT, traits>(t) <= sp |
sp <= t | sp <= basic_string_ref<charT, traits>(t) |
t >= sp | basic_string_ref<charT, traits>(t) >= sp |
sp >= t | sp >= basic_string_ref<charT, traits>(t) |
[ Example: A sample conforming implementation for operator== would be:
template<typename T> struct __identity { typedef T type; };
template<typename charT, typename traits>
bool operator==(basic_string_ref<charT, traits> lhs,
basic_string_ref<charT, traits> rhs) {
return lhs.compare(rhs) == 0;
}
template<typename charT, typename traits>
bool operator==(basic_string_ref<charT, traits> lhs,
typename __identity<basic_string_ref<charT, traits>>::type rhs) {
return lhs.compare(rhs) == 0;
}
template<typename charT, typename traits>
bool operator==(typename __identity<basic_string_ref<charT, traits>>::type lhs,
basic_string_ref<charT, traits> rhs) {
return lhs.compare(rhs) == 0;
}
— end example ]
template<class charT, class traits>
bool operator==(basic_string_ref<charT,traits> lhs,
basic_string_ref<charT,traits> rhs) noexcept;
Returns: lhs.compare(rhs) == 0.
template<class charT, class traits>
bool operator!=(basic_string_ref<charT,traits> lhs,
basic_string_ref<charT,traits> rhs) noexcept;
Returns: !(lhs == rhs).
template<class charT, class traits>
bool operator< (basic_string_ref<charT,traits> lhs,
basic_string_ref<charT,traits> rhs) noexcept;
Returns: lhs.compare(rhs) < 0.
template<class charT, class traits>
bool operator> (basic_string_ref<charT,traits> lhs,
basic_string_ref<charT,traits> rhs) noexcept;
Returns: lhs.compare(rhs) > 0.
template<class charT, class traits>
bool operator<=(basic_string_ref<charT,traits> lhs,
basic_string_ref<charT,traits> rhs) noexcept;
Returns: lhs.compare(rhs) <= 0.
template<class charT, class traits>
bool operator>=(basic_string_ref<charT,traits> lhs,
basic_string_ref<charT,traits> rhs) noexcept;
Returns: lhs.compare(rhs) >= 0.
template<class charT, class traits = char_traits<charT>,
class Allocator = allocator<charT> >
basic_string<charT, traits, Allocator> to_string(
basic_string_ref<charT, traits> str,
const Allocator& a = Allocator());
Complexity: O(str.size())
Returns: basic_string<charT, traits, Allocator>(str, a).
explicit // Footnote: This conversion is explicit to avoid accidental O(N) operations on type mismatches. --end footnote
basic_string(basic_string_ref<charT, traits>,
const Allocator& = Allocator());
basic_string& operator=(basic_string_ref<charT, traits>);
basic_string& operator+=(basic_string_ref<charT, traits>);
basic_string& append(basic_string_ref<charT, traits>);
basic_string& assign(basic_string_ref<charT, traits>);
basic_string& replace(const_iterator, const_iterator, basic_string_ref<charT, traits>);
operator basic_string_ref<charT, traits>() const noexcept;
bool starts_with(basic_string_ref<charT, traits> s) const noexcept;
bool starts_with(charT c) const noexcept;
bool starts_with(const charT* s) const noexcept;
bool ends_with(basic_string_ref<charT, traits> s) const noexcept;
bool ends_with(charT c) const noexcept;
bool ends_with(const charT* s) const noexcept;
explicit basic_string(basic_string_ref<charT, traits> str, const Allocator& a = Allocator());
Effects: Same as basic_string(str.begin(), str.end(), a).
This uses "Same as" instead of "Equivalent to" to be consistent with the rest of the basic_string specification.
operator basic_string_ref<charT, traits>() const noexcept;
Returns: basic_string_ref<charT, traits>(data(), size()).
Complexity: constant time.
Requires: The program shall not alter any of the values stored in the character array.
bool starts_with(const basic_string_ref<charT, traits>& prefix) const noexcept;
bool starts_with(charT prefix) const noexcept;
bool starts_with(const charT* prefix) const noexcept;
Effects: Equivalent to basic_string_ref<charT, traits>(*this).starts_with(prefix)
bool ends_with(const basic_string_ref<charT, traits>& suffix) const noexcept;
bool ends_with(charT suffix) const noexcept;
bool ends_with(const charT* suffix) const noexcept;
Effects: Equivalent to basic_string_ref<charT, traits>(*this).ends_with(suffix)
template<class charT, class traits, class Allocator>
basic_ostream<charT, traits>&
operator<<(basic_ostream<charT, traits>& os,
const basic_string<charT,traits,Allocator>& str);
template<class charT, class traits, class Allocator>
basic_ostream<charT, traits>&
operator<<(basic_ostream<charT, traits>& os,
basic_string_ref<charT,traits> str);
Effects: Behaves as a formatted output function
([ostream.formatted.reqmts]) of os
. Forms a character
sequence seq
, initially consisting of the elements defined by
the range [str.begin(), str.end())
. Determines padding for
seq
as described in [ostream.formatted.reqmts]. Then inserts
seq
as if by calling os.rdbuf()->sputn(seq, n)
,
where n
is the larger of os.width()
and
str.size()
; then calls os.width(0)
.
Returns: os
int stoi(string_ref str, size_t *idx = 0, int base = 10);
long stol(string_ref str, size_t *idx = 0, int base = 10);
unsigned long stoul(string_ref str, size_t *idx = 0, int base = 10);
long long stoll(string_ref str, size_t *idx = 0, int base = 10);
unsigned long long stoull(string_ref str, size_t *idx = 0, int base = 10);
float stof(string_ref str, size_t *idx = 0);
double stod(string_ref str, size_t *idx = 0);
long double stold(string_ref str, size_t *idx = 0);
int stoi(const char* str, size_t *idx = 0, int base = 10);
long stol(const char* str, size_t *idx = 0, int base = 10);
unsigned long stoul(const char* str, size_t *idx = 0, int base = 10);
long long stoll(const char* str, size_t *idx = 0, int base = 10);
unsigned long long stoull(const char* str, size_t *idx = 0, int base = 10);
float stof(const char* str, size_t *idx = 0);
double stod(const char* str, size_t *idx = 0);
long double stold(const char* str, size_t *idx = 0);
Each function of the forms
rt fn(string_ref str, size_t *idx = 0, int base = 10);
rt fn(const char* str, size_t *idx = 0, int base = 10);
is equivalent to fn(string(str), idx, base)
.
Each function of the forms
rt fn(string_ref str, size_t *idx = 0);
rt fn(const char* str, size_t *idx = 0);
is equivalent to fn(string(str), idx)
.
int stoi(wstring_ref str, size_t *idx = 0, int base = 10);
long stol(wstring_ref str, size_t *idx = 0, int base = 10);
unsigned long stoul(wstring_ref str, size_t *idx = 0, int base = 10);
long long stoll(wstring_ref str, size_t *idx = 0, int base = 10);
unsigned long long stoull(wstring_ref str, size_t *idx = 0, int base = 10);
float stof(wstring_ref str, size_t *idx = 0);
double stod(wstring_ref str, size_t *idx = 0);
long double stold(wstring_ref str, size_t *idx = 0);
int stoi(const wchar_t* str, size_t *idx = 0, int base = 10);
long stol(const wchar_t* str, size_t *idx = 0, int base = 10);
unsigned long stoul(const wchar_t* str, size_t *idx = 0, int base = 10);
long long stoll(const wchar_t* str, size_t *idx = 0, int base = 10);
unsigned long long stoull(const wchar_t* str, size_t *idx = 0, int base = 10);
float stof(const wchar_t* str, size_t *idx = 0);
double stod(const wchar_t* str, size_t *idx = 0);
long double stold(const wchar_t* str, size_t *idx = 0);
Each function of the forms
rt fn(wstring_ref str, size_t *idx = 0, int base = 10);
rt fn(const wchar_t* str, size_t *idx = 0, int base = 10);
is equivalent to fn(wstring(str), idx, base)
.
Each function of the forms
rt fn(wstring_ref str, size_t *idx = 0);
rt fn(const wchar_t* str, size_t *idx = 0);
is equivalent to fn(wstring(str), idx)
.
template <> struct hash<string_ref>;
template <> struct hash<u16string_ref>;
template <> struct hash<u32string_ref>;
template <> struct hash<wstring_ref>;
template <> struct hash<string>;
template <> struct hash<u16string>;
template <> struct hash<u32string>;
template <> struct hash<wstring>;
Requires: the template specializations shall meet the requirements of class template hash ([unord.hash]).
[ Note: All locale semantics are accessed via use_facet<> and has_facet<>, except that:
template <class charT, class traits, class Allocator>
bool operator()(const basic_string<charT,traits,Allocator>& s1,
const basic_string<charT,traits,Allocator>& s2) const;
template <class charT, class traits>
bool operator()(const basic_string_ref<charT,traits>& s1,
const basic_string_ref<charT,traits>& s2) const;
Effects: Compares two strings according to the collate<charT> facet.
Remarks: This member operator template (and therefore locale itself) satisfies requirements for a comparator predicate template argument (Clause 25) applied to strings.
Returns: The result of the following expression:
use_facet< collate<charT> >(*this).compare
namespace std {
template<class Codecvt, class Elem = wchar_t,
class Wide_alloc = std::allocator<Elem>,
class Byte_alloc = std::allocator<char> > class wstring_convert {
// ...
wide_string from_bytes(const basic_string_ref<char>& str);
byte_string to_bytes(const basic_string_ref<Elem>& wstr);
// ...
};
}
wide_string from_bytes(char byte);
wide_string from_bytes(const char *ptr);
wide_string from_bytes(const byte_string& str);
wide_string from_bytes(const basic_string_ref<char>& str);
wide_string from_bytes(const char *first, const char *last);
Effects: The first member function shall
convert the single-element sequence byte to a wide string. The second
member function shall convert the null-terminated sequence beginning at ptr
to a wide string. The third member function and fourth
member functions shall convert the sequence stored in str to a wide
string. The fourth fifth member function shall
convert the sequence defined by the range [first,last) to a wide
string.
byte_string to_bytes(Elem wchar);
byte_string to_bytes(const Elem *wptr);
byte_string to_bytes(const wide_string& wstr);
byte_string to_bytes(const basic_string_ref<Elem>& wstr);
byte_string to_bytes(const Elem *first, const Elem *last);
Effects: The first member function shall convert
the single-element sequence wchar to a byte string. The second member
function shall convert the null-terminated sequence beginning at wptr to a
byte string. The third member function and fourth member
functions shall convert the sequence stored in wstr to a byte
string. The fourth fifth member function shall convert
the sequence defined by the range [first,last) to a byte string.
template <class BiIter, class ST>
bool operator==(
basic_string_ref<
typename iterator_traits<BiIter>::value_type, ST> lhs,
const sub_match<BiIter>& rhs);
template <class BiIter, class ST>
bool operator!=(
basic_string_ref<
typename iterator_traits<BiIter>::value_type, ST> lhs,
const sub_match<BiIter>& rhs);
template <class BiIter, class ST>
bool operator<(
basic_string_ref<
typename iterator_traits<BiIter>::value_type, ST> lhs,
const sub_match<BiIter>& rhs);
template <class BiIter, class ST>
bool operator>(
basic_string_ref<
typename iterator_traits<BiIter>::value_type, ST> lhs,
const sub_match<BiIter>& rhs);
template <class BiIter, class ST>
bool operator>=(
basic_string_ref<
typename iterator_traits<BiIter>::value_type, ST> lhs,
const sub_match<BiIter>& rhs);
template <class BiIter, class ST>
bool operator<=(
basic_string_ref<
typename iterator_traits<BiIter>::value_type, ST> lhs,
const sub_match<BiIter>& rhs);
template <class BiIter, class ST>
bool operator==(
const sub_match<BiIter>& lhs,
basic_string_ref<
typename iterator_traits<BiIter>::value_type, ST> rhs);
template <class BiIter, class ST>
bool operator!=(
const sub_match<BiIter>& lhs,
basic_string_ref<
typename iterator_traits<BiIter>::value_type, ST> rhs);
template <class BiIter, class ST>
bool operator<(
const sub_match<BiIter>& lhs,
basic_string_ref<
typename iterator_traits<BiIter>::value_type, ST> rhs);
template <class BiIter, class ST>
bool operator>(
const sub_match<BiIter>& lhs,
basic_string_ref<
typename iterator_traits<BiIter>::value_type, ST> rhs);
template <class BiIter, class ST>
bool operator>=(
const sub_match<BiIter>& lhs,
basic_string_ref<
typename iterator_traits<BiIter>::value_type, ST> rhs);
template <class BiIter, class ST>
bool operator<=(
const sub_match<BiIter>& lhs,
basic_string_ref<
typename iterator_traits<BiIter>::value_type, ST> rhs);
template <class ST, class Allocator, class charT, class traits>
bool regex_match(basic_string_ref<charT, ST> s,
match_results<
typename basic_string_ref<charT, ST>::const_iterator,
Allocator>& m,
const basic_regex<charT, traits>& e,
regex_constants::match_flag_type flags =
regex_constants::match_default);
template <class ST, class charT, class traits>
bool regex_match(basic_string_ref<charT, ST> s,
const basic_regex<charT, traits>& e,
regex_constants::match_flag_type flags =
regex_constants::match_default);
template <class ST, class charT, class traits>
bool regex_search(basic_string_ref<charT, ST> s,
const basic_regex<charT, traits>& e,
regex_constants::match_flag_type flags =
regex_constants::match_default);
template <class ST, class Allocator, class charT, class traits>
bool regex_search(basic_string_ref<charT, ST> s,
match_results<
typename basic_string_ref<charT, ST>::const_iterator,
Allocator>& m,
const basic_regex<charT, traits>& e,
regex_constants::match_flag_type flags =
regex_constants::match_default);
template <class OutputIterator, class BidirectionalIterator,
class traits, class charT, class ST>
OutputIterator
regex_replace(OutputIterator out,
BidirectionalIterator first, BidirectionalIterator last,
const basic_regex<charT, traits>& e,
basic_string_ref<charT, ST> fmt,
regex_constants::match_flag_type flags =
regex_constants::match_default);
This wording does not include a fix for LWG issue 2216. That is, the new overloads always use the default allocator.
template <class traits, class charT, class ST, class FST>
basic_string<charT, ST>
regex_replace(basic_string_ref<charT, ST> s,
const basic_regex<charT, traits>& e,
basic_string_ref<charT, FST> fmt,
regex_constants::match_flag_type flags =
regex_constants::match_default);
template <class traits, class charT, class ST>
basic_string<charT, ST>
regex_replace(basic_string_ref<charT, ST> s,
const basic_regex<charT, traits>& e,
const charT* fmt,
regex_constants::match_flag_type flags =
regex_constants::match_default);
template <class traits, class charT, class ST>
basic_string<charT>
regex_replace(const charT* s,
const basic_regex<charT, traits>& e,
basic_string_ref<charT, ST> fmt,
regex_constants::match_flag_type flags =
regex_constants::match_default);
template <class traits, class charT, class ST, class SA,
class FST>
basic_string<charT, ST, SA>
regex_replace(const basic_string<charT, ST, SA>& s,
const basic_regex<charT, traits>& e,
basic_string_ref<charT, FST> fmt,
regex_constants::match_flag_type flags =
regex_constants::match_default);
template <class traits, class charT, class ST,
class FST, class FSA>
basic_string<charT, ST>
regex_replace(basic_string_ref<charT, ST> s,
const basic_regex<charT, traits>& e,
const basic_string<charT, FST, FSA>& fmt,
regex_constants::match_flag_type flags =
regex_constants::match_default);
template <class ST>
explicit basic_regex(basic_string_ref<charT, ST> p,
flag_type f = regex_constants::ECMAScript);
template <class ST>
basic_regex& operator=(basic_string_ref<charT, ST> p);
template <class string_traits>
basic_regex& assign(basic_string_ref<charT, string_traits> s,
flag_type f = regex_constants::ECMAScript);
template <class ST>
basic_regex(basic_string_ref<charT, ST> s,
flag_type f = regex_constants::ECMAScript);
template <class ST, class SA>
basic_regex(const basic_string<charT, ST, SA>& s,
flag_type f = regex_constants::ECMAScript);
Throws: regex_error if s is not a valid regular expression.
Effects: Constructs an object of class basic_regex; the object’s internal finite state machine is con- structed from the regular expression contained in the string s, and interpreted according to the flags specified in f.
Postconditions: flags() returns f. mark_count() returns the number of marked sub-expressions within the expression.
template <class ST>
basic_regex& operator=(basic_string_ref<charT, ST> p);
template <class ST, class SA>
basic_regex& operator=(const basic_string<charT, ST, SA>& p);
Effects: returns assign(p).
template <class string_traits>
basic_regex& assign(basic_string_ref<charT, string_traits> s,
flag_type f = regex_constants::ECMAScript);
template <class string_traits, class A>
basic_regex& assign(const basic_string<charT, string_traits, A>& s,
flag_type f = regex_constants::ECMAScript);
Throws: regex_error if s is not a valid regular expression.
Returns: *this.
Effects: Assigns the regular expression contained in the string s, interpreted according the flags specified in f. If an exception is thrown, *this is unchanged.
Postconditions: If no exception is thrown, flags() returns f and mark_count() returns the number of marked sub-expressions within the expression.
int compare(basic_string_ref<value_type> s) const;
int compare(basic_string_ref<value_type> s) const;
Returns: str().compare(s).
template <class BiIter, class ST>
bool operator==(
basic_string_ref<
typename iterator_traits<BiIter>::value_type, ST> lhs,
const sub_match<BiIter>& rhs);
Returns: rhs.compare(basic_string_ref<typename iterator_traits<BiIter>::value_type>(lhs.data(), lhs.size())) == 0.
[ Footnote: This and the other comparison operators ignore the basic_string_ref's traits. -- end footnote]
template <class BiIter, class ST>
bool operator!=(
basic_string_ref<
typename iterator_traits<BiIter>::value_type, ST> lhs,
const sub_match<BiIter>& rhs);
Returns: !(lhs == rhs).
template <class BiIter, class ST>
bool operator<(
basic_string_ref<
typename iterator_traits<BiIter>::value_type, ST> lhs,
const sub_match<BiIter>& rhs);
Returns: rhs.compare(basic_string_ref<typename iterator_traits<BiIter>::value_type>(lhs.data(), lhs.size())) > 0.
template <class BiIter, class ST>
bool operator>(
basic_string_ref<
typename iterator_traits<BiIter>::value_type, ST> lhs,
const sub_match<BiIter>& rhs);
Returns: rhs < lhs.
template <class BiIter, class ST>
bool operator>=(
basic_string_ref<
typename iterator_traits<BiIter>::value_type, ST> lhs,
const sub_match<BiIter>& rhs);
Returns: !(lhs < rhs).
template <class BiIter, class ST>
bool operator<=(
basic_string_ref<
typename iterator_traits<BiIter>::value_type, ST> lhs,
const sub_match<BiIter>& rhs);
Returns: !(rhs < lhs).
template <class BiIter, class ST>
bool operator==(const sub_match<BiIter>& lhs,
basic_string_ref<
typename iterator_traits<BiIter>::value_type, ST> rhs);
Returns: lhs.compare(basic_string_ref<typename iterator_traits<BiIter>::value_type>(rhs.data(), rhs.size())) == 0.
template <class BiIter, class ST>
bool operator!=(const sub_match<BiIter>& lhs,
basic_string_ref<
typename iterator_traits<BiIter>::value_type, ST> rhs);
Returns: !(lhs == rhs).
template <class BiIter, class ST>
bool operator<(const sub_match<BiIter>& lhs,
basic_string_ref<
typename iterator_traits<BiIter>::value_type, ST> rhs);
Returns: lhs.compare(basic_string_ref<typename iterator_traits<BiIter>::value_type>(rhs.data(), rhs.size())) < 0.
template <class BiIter, class ST>
bool operator>(const sub_match<BiIter>& lhs,
basic_string_ref<
typename iterator_traits<BiIter>::value_type, ST> rhs);
Returns: rhs < lhs.
template <class BiIter, class ST>
bool operator>=(const sub_match<BiIter>& lhs,
basic_string_ref<
typename iterator_traits<BiIter>::value_type, ST> rhs);
Returns: !(lhs < rhs).
template <class BiIter, class ST>
bool operator<=(const sub_match<BiIter>& lhs,
basic_string_ref<
typename iterator_traits<BiIter>::value_type, ST> rhs);
Returns: !(rhs < lhs).
template <class OutputIter, class ST>
OutputIter
format(OutputIter out,
basic_string_ref<char_type, ST> fmt,
regex_constants::match_flag_type flags =
regex_constants::format_default) const;
template <class ST>
basic_string<char_type, ST>
format(basic_string_ref<char_type, ST> fmt,
regex_constants::match_flag_type flags =
regex_constants::format_default) const;
template <class OutputIter, class ST>
OutputIter format(OutputIter out,
basic_string_ref<char_type, ST> fmt,
regex_constants::match_flag_type flags =
regex_constants::format_default) const;
template <class OutputIter, class ST, class SA>
OutputIter format(OutputIter out,
const basic_string<char_type, ST, SA>& fmt,
regex_constants::match_flag_type flags =
regex_constants::format_default) const;
Effects: Equivalent to return format(
.
template <class ST>
basic_string<char_type, ST>
format(basic_string_ref<char_type, ST>& fmt,
regex_constants::match_flag_type flags =
regex_constants::format_default) const;
Requires: ready() == true
.
Effects: Constructs an empty string result
of
type basic_string<char_type, ST>
and calls
format(back_inserter(result), fmt, flags)
.
Returns: result
.
template <class ST, class Allocator, class charT, class traits>
bool regex_match(basic_string_ref<charT, ST> s,
match_results<
typename basic_string_ref<charT, ST>::const_iterator,
Allocator>& m,
const basic_regex<charT, traits>& e,
regex_constants::match_flag_type flags =
regex_constants::match_default);
template <class ST, class SA, class Allocator, class charT, class traits>
bool regex_match(const basic_string<charT, ST, SA>& s,
match_results<
typename basic_string<charT, ST, SA>::const_iterator,
Allocator>& m,
const basic_regex<charT, traits>& e,
regex_constants::match_flag_type flags =
regex_constants::match_default);
Returns: regex_match(s.begin(), s.end(), m, e, flags).
template <class ST, class charT, class traits>
bool regex_match(basic_string_ref<charT, ST> s,
const basic_regex<charT, traits>& e,
regex_constants::match_flag_type flags =
regex_constants::match_default);
template <class ST, class SA, class charT, class traits>
bool regex_match(const basic_string<charT, ST, SA>& s,
const basic_regex<charT, traits>& e,
regex_constants::match_flag_type flags =
regex_constants::match_default);
Returns: regex_match(s.begin(), s.end(), e, flags).
template <class ST, class Allocator, class charT, class traits>
bool regex_search(basic_string_ref<charT, ST> s,
match_results<
typename basic_string_ref<charT, ST>::const_iterator,
Allocator>& m,
const basic_regex<charT, traits>& e,
regex_constants::match_flag_type flags =
regex_constants::match_default);
template <class ST, class SA, class Allocator, class charT, class traits>
bool regex_search(const basic_string<charT, ST, SA>& s,
match_results<
typename basic_string<charT, ST, SA>::const_iterator,
Allocator>& m,
const basic_regex<charT, traits>& e,
regex_constants::match_flag_type flags =
regex_constants::match_default);
Returns: The result of regex_search(s.begin(), s.end(), m, e, flags)
.
template <class ST, class SA, class charT, class traits>
bool regex_search(basic_string_ref<charT, ST>& s,
const basic_regex<charT, traits>& e,
regex_constants::match_flag_type flags =
regex_constants::match_default);
template <class ST, class SA, class charT, class traits>
bool regex_search(const basic_string<charT, ST, SA>& s,
const basic_regex<charT, traits>& e,
regex_constants::match_flag_type flags =
regex_constants::match_default);
Returns: regex_search(s.begin(), s.end(), e, flags)
.
template <class OutputIterator, class BidirectionalIterator,
class traits, class charT, class ST, class SA>
OutputIterator
regex_replace(OutputIterator out,
BidirectionalIterator first, BidirectionalIterator last,
const basic_regex<charT, traits>& e,
const basic_string<charT, ST, SA>& fmt,
regex_constants::match_flag_type flags =
regex_constants::match_default);
template <class OutputIterator, class BidirectionalIterator,
class traits, class charT, class ST>
OutputIterator
regex_replace(OutputIterator out,
BidirectionalIterator first, BidirectionalIterator last,
const basic_regex<charT, traits>& e,
basic_string_ref<charT, ST> fmt,
regex_constants::match_flag_type flags =
regex_constants::match_default);
template <class OutputIterator, class BidirectionalIterator,
class traits, class charT>
OutputIterator
regex_replace(OutputIterator out,
BidirectionalIterator first, BidirectionalIterator last,
const basic_regex<charT, traits>& e,
const charT* fmt,
regex_constants::match_flag_type flags =
regex_constants::match_default);
Effects: Constructs a regex_iterator object i as if by regex_iterator<BidirectionalIterator, charT, traits> i(first, last, e, flags), and uses i to enumerate through all of the matches m of type match_results<BidirectionalIterator> that occur within the sequence [first,last ). If no such matches are found and !(flags & regex_constants ::format_no_copy) then calls std::copy(first, last, out). If any matches are found then, for each such match, if !(flags & regex_constants::format_no_copy), calls std::copy(m.prefix().first, m.prefix().second, out), and then calls m.format(out, fmt, flags) for the first form and second forms of the function and m.format(out, fmt, fmt + char_traits<charT>::length(fmt), flags) for the second third. Finally, if such a match is found and !(flags & regex_constants ::format_no_copy), calls std:: copy(last_m.suffix().first, last_m.suffix().second, out) where last_m is a copy of the last match found. If flags & regex_constants::format_first_only is non-zero then only the first match found is replaced.
Returns: out.
template <class traits, class charT, class ST, class FST, class FSA>
basic_string<charT, ST>
regex_replace(basic_string_ref<charT, ST> s,
const basic_regex<charT, traits>& e,
const basic_string<charT, FST, FSA>& fmt,
regex_constants::match_flag_type flags =
regex_constants::match_default);
template <class traits, class charT, class ST, class FST>
basic_string<charT, ST>
regex_replace(basic_string_ref<charT, ST> s,
const basic_regex<charT, traits>& e,
basic_string_ref<charT, FST> fmt,
regex_constants::match_flag_type flags =
regex_constants::match_default);
template <class traits, class charT, class ST>
basic_string<charT, ST>
regex_replace(basic_string_ref<charT, ST> s,
const basic_regex<charT, traits>& e,
const charT* fmt,
regex_constants::match_flag_type flags =
regex_constants::match_default);
Effects: Constructs an empty string result of type basic_string<charT, ST> and calls regex_replace(back_inserter(result), s.begin(), s.end(), e, fmt, flags).
Returns: result.
template <class traits, class charT, class ST, class SA, class FST, class FSA>
basic_string<charT, ST, SA>
regex_replace(const basic_string<charT, ST, SA>& s,
const basic_regex<charT, traits>& e,
const basic_string<charT, FST, FSA>& fmt,
regex_constants::match_flag_type flags =
regex_constants::match_default);
template <class traits, class charT, class ST, class SA, class FST>
basic_string<charT, ST, SA>
regex_replace(const basic_string<charT, ST, SA>& s,
const basic_regex<charT, traits>& e,
basic_string_ref<charT, FST> fmt,
regex_constants::match_flag_type flags =
regex_constants::match_default);
template <class traits, class charT, class ST, class SA>
basic_string<charT, ST, SA>
regex_replace(const basic_string<charT, ST, SA>& s,
const basic_regex<charT, traits>& e,
const charT* fmt,
regex_constants::match_flag_type flags =
regex_constants::match_default);
Effects: Constructs an empty string result of type basic_string<charT, ST, SA> and calls regex_replace(back_inserter(result), s.begin(), s.end(), e, fmt, flags).
Returns: result.
template <class traits, class charT, class ST, class SA>
basic_string<charT>
regex_replace(const charT* s,
const basic_regex<charT, traits>& e,
const basic_string<charT, ST, SA>& fmt,
regex_constants::match_flag_type flags =
regex_constants::match_default);
template <class traits, class charT, class ST>
basic_string<charT>
regex_replace(const charT* s,
const basic_regex<charT, traits>& e,
basic_string_ref<charT, ST> fmt,
regex_constants::match_flag_type flags =
regex_constants::match_default);
template <class traits, class charT>
basic_string<charT>
regex_replace(const charT* s,
const basic_regex<charT, traits>& e,
const charT* fmt,
regex_constants::match_flag_type flags =
regex_constants::match_default);
Effects: Constructs an empty string result of type basic_string<charT> and calls regex_replace( back_inserter(result), s, s + char_traits<charT>::length(s), e, fmt, flags).
Returns: result.
I'd like to thank Marshall Clow, Olaf van der Spek, the Boost and std-proposals mailing lists, Chandler Carruth, Beman Dawes, Daniel Krügler, and Alisdair Meredith for help, advice, and wording in this paper.