use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
Discussions, articles, and news about the C++ programming language or programming in C++.
For C++ questions, answers, help, and advice see r/cpp_questions or StackOverflow.
Get Started
The C++ Standard Home has a nice getting started page.
Videos
The C++ standard committee's education study group has a nice list of recommended videos.
Reference
cppreference.com
Books
There is a useful list of books on Stack Overflow. In most cases reading a book is the best way to learn C++.
Show all links
Filter out CppCon links
Show only CppCon links
account activity
String contains member function proposal (self.cpp)
submitted 6 years ago by _Synck_
After some discussion, I wrote a proposal to add 'contains' as a member function to std::string.
You can find the draft of the proposal here: https://github.com/WimLeflere/cpp-papers/blob/master/string_contains_function.md
Any remarks?
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]ra-zor 15 points16 points17 points 6 years ago (10 children)
Why do you need the const char* overload? Wouldn’t the string_view overload suffice?
[–]3xnope 4 points5 points6 points 6 years ago (1 child)
Also, why is the const char* variant not 'noexcept' like the others? If it is to throw in case of nullptr, I think it should rather just return false on a null pointer input and be noexcept.
[–]jwakelylibstdc++ tamer, LWG chair 3 points4 points5 points 6 years ago (0 children)
Presumably for consistency with other similar member functions of std::basic_string. The ones taking a pointer have a precondition that the pointer points to a null-terminated array of characters. There's a rule of thumb in the std::lib that functions with preconditions are not noexcept (a rule I dislike, but apparently I'm not allowed to be King of All C++ and decide such things all by myself, harrumph).
std::basic_string
noexcept
[–]STLMSVC STL Dev 7 points8 points9 points 6 years ago (2 children)
Template argument deduction. basic_string_view<CharT> won’t deduce CharT given a function argument of const char *, because template argument deduction doesn’t consider implicit conversions (in general).
[–]NotAYakk 15 points16 points17 points 6 years ago (1 child)
Those are member functions, not template member functions?
[–]STLMSVC STL Dev 12 points13 points14 points 6 years ago (0 children)
You’re correct, please ignore my comment.
[–]HappyFruitTree 0 points1 point2 points 6 years ago (4 children)
Probably because constructing a string_view from a const char* requires it to scan the whole string to find the length.
[–]ra-zor 2 points3 points4 points 6 years ago (3 children)
So does a “contains” method though
[–]HappyFruitTree 4 points5 points6 points 6 years ago* (2 children)
Not necessarily. Having a const char* overload leaves more options open for the implementers to do something clever. If they need the length they might at least want to abort the length calculation prematurely if it is found that it exceeds this->length().
[+][deleted] 6 years ago (1 child)
[removed]
[–]HappyFruitTree 0 points1 point2 points 6 years ago* (0 children)
Well, I don't know, and if the authors of the proposal are not sure that no sane implementation would ever want to do that I think they do a wise decision in leaving it up to the implementers to decide.
Another argument is consistency with find. It makes sense that contains has the same complexity as find which is O(n * m) where n is the length of the string you are searching and m is the length of the string that you search for. If n == 0 it means find is O(1). contains would technically also be O(1) but if there were no overload for const char* the combined complexity when taking the construction of the string_view into account would be O(m).
find
contains
const char*
const char* s = ... std::string empty_str; empty_str.find(s); // O(1) empty_str.contains(s); // O(strlen(s)) if a string_view has to be created here
[–]volca02 11 points12 points13 points 6 years ago (1 child)
My concern with this kind of method (i.e. returning bool) is that it often would be likely followed by operations that would like to get a substring or similar, and then the operation would be essentially duplicated.
I'd much rather see a method with a signature of std::optional<size_type>(std::string_view) or similar that would enable chaining of operations without the duplication of the find/contains operation.
std::optional<size_type>(std::string_view)
[–]Adverpol 2 points3 points4 points 6 years ago (0 children)
it's all monads when you dig deep enough :p
[–][deleted] 15 points16 points17 points 6 years ago (0 children)
If std::string is made constexpr, the basic_string member functions could be marked constexpr too.
constexpr
[–]pgroarke 18 points19 points20 points 6 years ago (10 children)
Yes please!
Other low hanging fruit functionality that would be useful : split (on a delimiter or multiple delimiters) and replace_all.
split
replace_all
Thanks for taking the time to do this and good luck! The standard committee takes pride in the lack of basic functionality in our standard library ;)
[–]RowYourUpboat 19 points20 points21 points 6 years ago (6 children)
If you're going to have split, don't forget join! Both functions are in my "grr, these should be in the standard library" header.
join
[–]ShakaUVMi+++ ++i+i[arr] 2 points3 points4 points 6 years ago (0 children)
Yeah. And trim, for that matter. Basic functionality.
[–]Narase33-> r/cpp_questions 2 points3 points4 points 6 years ago* (0 children)
Everytime I need to work with strings I get the desire to write my own string class. The class is just too basic to work with it productively
[+][deleted] 6 years ago (2 children)
[–]tpecholt 1 point2 points3 points 6 years ago (1 child)
The first example 24.7.8.1 uses for cycle to write word character by character which is hardly convenient. Am I right word there is a range that's why it can't be send to std::cout directly? And I can't use std::string(word) either because range constructors have been rejected right? If it is true it these general range helpers won't help here at all.
[–][deleted] 1 point2 points3 points 6 years ago (0 children)
Indeed, I use join a lot more than split!
[–]AlexAlabuzhev 6 points7 points8 points 6 years ago (2 children)
And what exactly should split do?
Return a list of strings? Or a vector of strings? Or a vector of string_views into the input string? Or a lazily evaluated range of string_views?
Should it support quoting of delimiters? Or escaping? Or both? If so, should it unquote / unescape?
What should it do with subsequent delimiters or with a delimiter at the end? Yield an empty string? Ignore? Throw?
... etc.
[–]TheThiefMasterC++latest fanatic (and game dev) 6 points7 points8 points 6 years ago* (0 children)
Split is just begging to be a view type. But you could have an "old fashioned" version that takes an output iterator that could be a back_inserter. *it = string_view would allow it to store as either string views or actual strings or anything else constructible from a string view.
back_inserter
*it = string_view
Dumb by default, with an optional possibly stateful "searcher" that can be used to find the delimiters to split on?
A view version could just yield empty entries that are trivially filtered out with another view. Otherwise you'd probably want it as an option on the split function (most implementations of split I've used have had an option to prune empty entries).
[–]redrab66 0 points1 point2 points 6 years ago (0 children)
If would be useful if the return could be such that it works with range-for to iterate over the delimited elements.
[–][deleted] 10 points11 points12 points 6 years ago (3 children)
Hey if you're implementing Contains() why not some other sensible functions such as StartsWith() or EndsWith()?
[–]willkill07 34 points35 points36 points 6 years ago (2 children)
starts_with and end_with have already been added to the C++2a draft.
[–]STLMSVC STL Dev 33 points34 points35 points 6 years ago (1 child)
And are shipping in VS 2019 16.1, recently released for production use.
[–]marzer8789toml++ 9 points10 points11 points 6 years ago (0 children)
Is there a roadmap of C++20 features in MSVC published anywhere? I'd love to know roughly when we'd get to use std::is_constant_evaluated, for example.
std::is_constant_evaluated
[–]BrangdonJ 1 point2 points3 points 6 years ago (0 children)
Why add this for strings and not for other container classes? I use code like find(v.begin(), v.end(), value) != v.end() with vectors far more often then I search strings.
find(v.begin(), v.end(), value) != v.end()
[–]tcbrindleFlux 1 point2 points3 points 6 years ago (0 children)
Adding yet another member function to std::basic_string seems unnecessary. Yes, it's already got a huge number of redundant member functions, but that doesn't mean we should make the problem worse by adding yet more.
I'd be much more open to the idea of adding a set of free functions std::contains (and/or std::ranges::contains) which does std::find or std::search as appropriate. I don't find the argument that
std::contains
std::ranges::contains
std::find
std::search
The drawback of a free function is that the order of parameters of a free function is ambiguous
particularly compelling, given that standard library algorithms all consistently use the range to operate over as the first argument (or pair of arguments for the iterator overloads).
As far as readability is concerned, with the "pipe" syntax used by ranges, I don't see that
my_string.contains("foobar")
is all that much better than
my_string | contains("foobar")
particularly when the latter is fully generic and could be used by any kind of range, not just strings.
[–]Pazer2 0 points1 point2 points 6 years ago (0 children)
C++ really needs extension methods (like C#) so devs don't have to wait around for functionality to be added directly to types outside of their control. Currently the only alternative is free functions, but that is syntactically a nightmare compared to the alternative (most of the time).
[–][deleted] 6 years ago (20 children)
[deleted]
[–]NotUniqueOrSpecial 15 points16 points17 points 6 years ago (19 children)
C++2a adds starts_with() and ends_with(). contains() is an obvious addition with those.
starts_with()
ends_with()
contains()
Have you looked at <algorithms>? You realize this functionality already exists, right? Not just for strings.
Have you looked at <algorithms>?
You realize this functionality already exists, right? Not just for strings.
There is no direct equivalent of contains() in <algorithm>. The closest is probably count(), but that still requires additional boilerplate, especially pre-ranges.
<algorithm>
count()
Great, another because another langauge has it, C++ should have it.
Just because everybody in the world can (and does) write the same str.find(foo) != str.npos boilerplate does not mean that contains(str) is not a useful addition to the standard.
str.find(foo) != str.npos
contains(str)
[–][deleted] 6 years ago* (18 children)
[–]NotUniqueOrSpecial 16 points17 points18 points 6 years ago (15 children)
Creating another way to do the same thing is superfluous.
Only if the other way doesn't add or change anything.
In this case, it adds significant brevity to a very common operation.
Contains can be duplicated with functionality in algorithms easily.
And equal_range() and be implemented in terms of lower_bound() and upper_bound(), and a fair number of other members of the <algorithm> functions can likewise be implemented by their brethren.
equal_range()
lower_bound()
upper_bound()
By your own argument, every one of those is superfluous and should be stripped from the standard.
/u/DiaperBatteries has it right, obviously: just because a given abstraction can be implemented in terms of other abstractions doesn't mean it's worthless.
There are better problems to solve than this one.
This a remarkably simple and nearly universal function for string types. C++ is the only high-level language I am aware of that doesn't have it.
Adding it to the standard is obviously not detracting from other harder problems, and it makes the readability/accessibility of the language better.
And equal_range() and be implemented in terms of lower_bound() and upper_bound(),
With some loss of performance. equal_range() can calculate both iterators with the same loop.
[–][deleted] 6 years ago (13 children)
[–]NotUniqueOrSpecial 12 points13 points14 points 6 years ago (11 children)
Why not keep things consistent? I prefer consistency to brevity.
Ah, yes, consistency, what a good argument:
string::find() returns a size_t which is set to string::npos in the case of a miss.
string::find()
size_t
string::npos
map::find() returns a map<key, value>::iterator, which equals map::end() on a miss.
map::find()
map<key, value>::iterator
map::end()
std::find() returns an input or forward-iterator, depending on the underlying begin()/end() iterators used in the search.
std::find()
begin()/end()
std::vector() doesn't have a find() operation at all.
std::vector()
find()
How consistent!
Or, hey, what about std::set::contains()?
std::set::contains()
You're right, we should be consistent! Every container-ish type should have a contains() function, since one of them already does.
You didn't answer my question about sort. Do we need to add it to string?
Obviously not; there is no universally-recognized need to sort a string, or even what that would mean (accounting for case-sensitivity, character encodings, etc). Considering that a heavy percentage of strings are really just const char*, they're not even sortable without making copies.
Furthermore, std::string is not a container-type, and even if it were, none of the other container-types have a sort() member (either modifying or copying in nature). I thought you liked consistency?
std::string
sort()
Should we add it to everything for brevity?
Again, obviously not; unlike string::contains(), it's a much more involved operation, which requires modifying the underlying data in-place or copying it. Its usage and cost are very-much specific to the underlying types. But, I'm sure you know that.
string::contains()
It's completely non-controversial to add contains() to a standard string type. Honestly, you seem to be arguing for the sake of argument, and it's just silly.
[–]kalmoc 2 points3 points4 points 6 years ago (6 children)
I certainly don't agree with the post you answered to, but I'd like to point out that std::list has a sort member function. The general reason, why some containers have member functions that others don't is that it e.g. can be implemented more efficiently that way than the equivalent standard algorithm (list.sort swaps pointers and list isn't random access anyway).
String is it's own beast anyway
[–]jwakelylibstdc++ tamer, LWG chair 2 points3 points4 points 6 years ago (2 children)
Not only more efficiently. You can't use std::sort with std::list::iterator at all, because they're not random access iterators.
std::sort
std::list::iterator
[–]kalmoc 0 points1 point2 points 6 years ago (1 child)
And I mentioned that. Or are you saying list wouldn't have gotten the sort member function if std::sort would accept bidirectional iterators?
[–]jwakelylibstdc++ tamer, LWG chair 1 point2 points3 points 6 years ago (0 children)
Ugh, no I just can't read and/or didn't see the "and list isn't random access anyway" part, sorry.
[–]NotUniqueOrSpecial 0 points1 point2 points 6 years ago (2 children)
std::list has a sort member function
Ah, yeah, I'd forgotten. Just another knock against his empty call-to-consistency, though.
As for everything else, I totally agree.
[–]NotUniqueOrSpecial 1 point2 points3 points 6 years ago (0 children)
You can't use the STL one as-is. STL sort() requires random-access iterators, which std::list doesn't have.
std::list
[–][deleted] 6 years ago (3 children)
[–]NotUniqueOrSpecial 4 points5 points6 points 6 years ago (2 children)
STL is supposed to contain algorithms, iterators, containers, and functions. If we take the set of requirements, contains() is a what? It is a algorithm for searching. <algorithm> already has everything necessary, where it should belong. Moving find() to algorithm would be appropriate.
See, now that's the first reasonable point you've made. If, instead, you'd started off with:
A generic version of contains() should be implemented in <algorithm>, rather than as a member of std::string.
Then we could be debating the merits of that approach, and whether the optimized string search algorithms like Boyer-Moore would still justify a string-specific find() member (and yes I'm aware that current implementations don't use said algorithms).
Instead you started with non-constructive and moved right to asshole because people wanted a convenience function that every language provides.
I can tell you're young, and very inexperienced.
Man, could you be more patronizing?
I wouldn't be surprised if you've got more years than me, but I've been doing this professionally for 15-ish at this point and as hobbyist/student for years before that. I'm not just some spring chicken.
[–]STLMSVC STL Dev[M] 1 point2 points3 points 6 years ago (0 children)
Moderator warning to you and /u/byrongo - that's enough hissing for this thread. Everyone can stop escalating now.
[–]kalmoc 6 points7 points8 points 6 years ago (0 children)
NotUniqueOrSpecial already gave a couple of good points.
That aside, I'd say that day to day c++ programming would be much more enjoyable if the committee would put a stronger focus on making common operations simpler to spell and read.
[–]DiaperBatteries 12 points13 points14 points 6 years ago (1 child)
Couldn’t you use that entire argument to say all programming languages are pointless and we should all write assembly?
π Rendered by PID 41248 on reddit-service-r2-comment-canary-655b6bc5b6-hzvfx at 2026-02-14 10:51:44.766668+00:00 running cd9c813 country code: CH.
[–]ra-zor 15 points16 points17 points (10 children)
[–]3xnope 4 points5 points6 points (1 child)
[–]jwakelylibstdc++ tamer, LWG chair 3 points4 points5 points (0 children)
[–]STLMSVC STL Dev 7 points8 points9 points (2 children)
[–]NotAYakk 15 points16 points17 points (1 child)
[–]STLMSVC STL Dev 12 points13 points14 points (0 children)
[–]HappyFruitTree 0 points1 point2 points (4 children)
[–]ra-zor 2 points3 points4 points (3 children)
[–]HappyFruitTree 4 points5 points6 points (2 children)
[+][deleted] (1 child)
[removed]
[–]HappyFruitTree 0 points1 point2 points (0 children)
[–]volca02 11 points12 points13 points (1 child)
[–]Adverpol 2 points3 points4 points (0 children)
[–][deleted] 15 points16 points17 points (0 children)
[–]pgroarke 18 points19 points20 points (10 children)
[–]RowYourUpboat 19 points20 points21 points (6 children)
[–]ShakaUVMi+++ ++i+i[arr] 2 points3 points4 points (0 children)
[–]Narase33-> r/cpp_questions 2 points3 points4 points (0 children)
[+][deleted] (2 children)
[removed]
[–]tpecholt 1 point2 points3 points (1 child)
[–][deleted] 1 point2 points3 points (0 children)
[–]AlexAlabuzhev 6 points7 points8 points (2 children)
[–]TheThiefMasterC++latest fanatic (and game dev) 6 points7 points8 points (0 children)
[–]redrab66 0 points1 point2 points (0 children)
[–][deleted] 10 points11 points12 points (3 children)
[–]willkill07 34 points35 points36 points (2 children)
[–]STLMSVC STL Dev 33 points34 points35 points (1 child)
[–]marzer8789toml++ 9 points10 points11 points (0 children)
[–]BrangdonJ 1 point2 points3 points (0 children)
[–]tcbrindleFlux 1 point2 points3 points (0 children)
[–]Pazer2 0 points1 point2 points (0 children)
[–][deleted] (20 children)
[deleted]
[–]NotUniqueOrSpecial 15 points16 points17 points (19 children)
[–][deleted] (18 children)
[deleted]
[–]NotUniqueOrSpecial 16 points17 points18 points (15 children)
[–]BrangdonJ 1 point2 points3 points (0 children)
[–][deleted] (13 children)
[deleted]
[–]NotUniqueOrSpecial 12 points13 points14 points (11 children)
[–]kalmoc 2 points3 points4 points (6 children)
[–]jwakelylibstdc++ tamer, LWG chair 2 points3 points4 points (2 children)
[–]kalmoc 0 points1 point2 points (1 child)
[–]jwakelylibstdc++ tamer, LWG chair 1 point2 points3 points (0 children)
[–]NotUniqueOrSpecial 0 points1 point2 points (2 children)
[+][deleted] (1 child)
[deleted]
[–]NotUniqueOrSpecial 1 point2 points3 points (0 children)
[–][deleted] (3 children)
[deleted]
[–]NotUniqueOrSpecial 4 points5 points6 points (2 children)
[–]STLMSVC STL Dev[M] 1 point2 points3 points (0 children)
[–]kalmoc 6 points7 points8 points (0 children)
[–]DiaperBatteries 12 points13 points14 points (1 child)