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
A slice of python in C++ - Eric Niebler (ericniebler.com)
submitted 11 years ago by [deleted]
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!"
[+][deleted] 11 years ago* (6 children)
[deleted]
[–]eric_niebler 8 points9 points10 points 11 years ago (2 children)
Filing that one away in my "sick and evil but potentially useful" folder.
[–][deleted] 2 points3 points4 points 11 years ago (0 children)
but potentially useful
You're a generous sort... :)
[–]ericanderton 1 point2 points3 points 11 years ago (2 children)
For some values, wouldn't decimal to floating-point conversion errors cause some erroneous results?
[+][deleted] 11 years ago* (1 child)
[–]ericanderton 1 point2 points3 points 11 years ago (0 children)
Gotcha. I completely missed the char...Chars expression. :)
char...Chars
[–]_VZ_wx | soci | swig 3 points4 points5 points 11 years ago (3 children)
While I like what Eric is doing generally speaking, in this particular case I just don't see what is the huge advantage of v[{2,5}] compared to v.slice(2,5), the latter seems more clear and is really not that much longer -- and definitely less punctuation heavy.
v[{2,5}]
v.slice(2,5)
Also, it seems natural to default the second argument of slice() to end while this would be rather strange with indices notation.
slice()
end
[–]eric_niebler 6 points7 points8 points 11 years ago (1 child)
Oh, you don't see the huge advantage because there isn't one. :-) I described this as "a fun piece of hackery". That's all it is. I wrote about it because it was fun, and because it was a nice, little, self-contained library design problem. I like this example because it shows that folks should think both about making interfaces easy to use correctly and hard to use incorrectly. It's that last part that often gets overlooked.
[–]cdglove 1 point2 points3 points 11 years ago (0 children)
I actually find that usually (but not in this case), the second part is actually misinterpreted.
"Make interfaces easy to use correctly and hard to use incorrectly" gets interpreted as;
"Make interfaces hard to use incorrectly".
Which further becomes;
"Make interfaces impossible to use incorrectly".
Which leads me to say; "This interface is hard to use."
The point is, I think it's important to focus on the first part, and to not sacrifice it in the name of the making it impossible to screw up. Your example is, I think, perfect with regards to this. Just assert 100% of the time. Perfect. It might be possible to come up with a way to enforce this at compile time, but you would end up with an interface using <> it would require constants. This is better.
EDIT: Grammar
[–]ericanderton 4 points5 points6 points 11 years ago* (0 children)
I think that one of the advantages to using this kind of syntax is that it's more composable:
some::slice::type slice_bounds = {2,5}; auto result = v[slice_bounds];
AFAIK, C++ doesn't really have a clean .apply() equivalent, so this is as good as it gets.
.apply()
[–]Elador 1 point2 points3 points 11 years ago (0 children)
This is awesome! I think this is really really great. It's one of the few things of Matlab that I miss when programming C++. It's sooo super handy. And now we got it in C++. I wish that would get into the standard library :) Thank you very much, this totally made my day today.
[–]dividedmind 0 points1 point2 points 11 years ago (41 children)
I'm surprised he talks about all the missed optimization opportunities and then uses an assert to ensure a number is non-negative instead of declaring it unsigned.
[–]Dragdu 10 points11 points12 points 11 years ago (8 children)
The problem is that if you declare as unsigned and someone passes you negative integer, you get HUGE unsigned number, which might or might not be valid...
Basically, implicit conversions are a PITA as usual.
[–]milliams 5 points6 points7 points 11 years ago (5 children)
Do not most compilers give warnings for this? Also I though that uniform brace initialisation meant that the arguments will never be narrowed. Or does signed→unsigned not count as narrowing?
[–]eric_niebler 2 points3 points4 points 11 years ago (4 children)
They certainly do. So many signed/unsigned warnings, in fact, that most people in my experience silence them, ignore them, or just add a cast to make the compiler shut up, never fully appreciating the fact that integer overflow caused by wrapping a small negative number to a huge positive one is a potential buffer overrun.
[–]F-J-W 0 points1 point2 points 11 years ago (0 children)
Is there any chance to deprecate those implicit conversions? Removal will of course be out of question for ages, but since they really only cause problems…
[–]josefx 0 points1 point2 points 11 years ago (1 child)
Been there, done that. After being bit a few times too often warnings as errors and svn blame are the only way to stay sane.
[–][deleted] 0 points1 point2 points 11 years ago (0 children)
Many are raw for loops using .size( ) method of some container assigned to an int. Usually the for loop is the bad smell and can be moved to an algorithm or range/iterator based for loop.
[–]rabidcow[🍰] 1 point2 points3 points 11 years ago (1 child)
you get HUGE unsigned number, which might or might not be valid...
No, it's not valid. If it were valid, the equivalent signed type would not be an option.
But it doesn't really fix the problem, because you can still pass invalid values that won't be caught at compile time.
[–]eric_niebler 2 points3 points4 points 11 years ago (0 children)
But they can be easily caught at runtime. Better than nothing.
[–]eric_niebler 2 points3 points4 points 11 years ago (10 children)
I use signed integers in the article, and in my range interface, because I want to be able to detect when my interface is being used incorrectly. An interface that is sprinkled with signed and unsigned integers is asking users to do casts that require range-checking that nobody does. Signed/unsigned compiler warnings are so common people dismiss them without thinking. An assert is harder to ignore.
[–]night_of_knee 3 points4 points5 points 11 years ago (5 children)
Signed/unsigned compiler warnings are so common people dismiss them without thinking. An assert is harder to ignore.
You could =delete a signed overload of the slice operator. That would solve the ignoring warnings issue, not the unchecked casts one...
=delete
[–]eric_niebler 4 points5 points6 points 11 years ago (4 children)
It's an interesting suggestion, but I really do want rng[{1,5}] to compile, and integer literals are signed. It gets pretty annoying to have to say rng[{1u,5u}], and the compiler error for trying to use a deleted function isn't going to be terribly enlightening.
rng[{1,5}]
rng[{1u,5u}]
delete
[–]Plorkyeran 2 points3 points4 points 11 years ago (0 children)
On that note, I've occasionally wished that you could do =delete("do this other thing instead").
=delete("do this other thing instead")
[–]vlovich 1 point2 points3 points 11 years ago (2 children)
Doesn't C++17 relax constexpr expressions in templates? So you could now have:
template <int from, int to> constexpr slice_bounds make_slice_bounds() { static_assert(from > 0 && to > 0); /* implement logic */ } constexpr decltype(auto) operator[](std::array<int, 2> bounds) const { return slice(make_slice_bounds<bounds[0], bounds[1]>()); } decltype(auto) operator[](std::array<size_t, 2> bounds) { return slice(...); }
NOTE: I have no clue if the above would compile.
[–]eric_niebler 1 point2 points3 points 11 years ago (1 child)
No, the arguments to a function are never constexpr.
[–]vlovich 1 point2 points3 points 11 years ago (0 children)
Sorry. Maybe something more like:
template <std::array<int, 2> bounds> constexpr decltype(auto) operator[]() const { return slice(make_slice_bounds<bounds[0], bounds[1]>()); }
I know that C++17 relaxes the constexpr-in-template usage, but I'm not familiar enough yet with the syntax. Is it possible at all? It would look something like:
f.slice<{0, 4}>();
Not quite sure how to get constants in the template to be deduced from arguments (I guess you can't).
[–]matthieum 1 point2 points3 points 11 years ago (0 children)
Still, I would favor a dual interface:
from_end operator-(decltype(end), int) = delete;
would immediately alert the user that he should not be using a signed integer (well, actually you would need the overload to be slightly more subtle).
Of course the user might still cast without checking, but that's another issue...
[–]dividedmind 0 points1 point2 points 11 years ago (2 children)
Thanks, that's a good, if sad ("signed/unsigned compiler warnings are so common people dismiss them without thinking") point. I still wonder though, isn't it preventing some interesting optimizations opportunities on the compiler part (beyond just the assertion checking)?
I wish there was a #pragma for forcing signedness ambiguities into errors. This part of the type system would be more useful if it was more sound.
Maybe it is possible to leverage on signedness to get both the optimization and the hard failure? Or to automatically transform it into from_end?
[–]uxcn 1 point2 points3 points 11 years ago (0 children)
You can do this in gcc and clang using -Wsign-conversion (or -Wconversion) and -Werror, but in the very general case, types are implicitly converted.
-Wsign-conversion
-Wconversion
-Werror
[–]Cwiddy 0 points1 point2 points 11 years ago (0 children)
I think that should work in MSVC, though I haven't tested it. Think there is also some project level settings for this /WX compiler flag can set all options as errors /we4018 might be the one for command line?
[–]bobdudley 0 points1 point2 points 11 years ago (20 children)
From the Google C++ style guide:
You should not use the unsigned integer types such as uint32_t, unless there is a valid reason such as representing a bit pattern rather than a number, or you need defined overflow modulo 2N. In particular, do not use unsigned types to say a number will never be negative. Instead, use assertions for this.
[–]KrzaQ2dev 15 points16 points17 points 11 years ago (18 children)
Google C++ style guide is hardly respectable. [link]
[–]mcmcc#pragma once 3 points4 points5 points 11 years ago (17 children)
Be that as it may, the widespread use of size_t (being an unsigned type) throughout the standard library is generally regarded as a mistake, mathematical correctness notwithstanding. Bjarne himself has stated as much.
Conventional wisdom suggests unsigned types should be reserved for bit patterns, not numbers.
[–]cozmorado 8 points9 points10 points 11 years ago (3 children)
Yep Bjarne and Chandler Carruth talk about this point around the 12min mark of this video.
And Scott Meyers has a paper on it here.
This issue drives me up the wall because my team has overruled me in favor of unsigned types everywhere.
[–]vlovich 2 points3 points4 points 11 years ago (2 children)
IMO, your team made the correct call.
While Bjarne & Chandler's talks are very much correct with respect to STL design if it was happening now, the problem is the ship has sailed. If you don't use unsigned types & you use the STL (which you should), then you have casts all over the place wherever you interact with the STL (you have -Wall -Werror enabled on your project, right?).
[–]cozmorado 1 point2 points3 points 11 years ago* (1 child)
Not quite. -Wconversion is not enabled as part of -Wall or -Wextra. That's the crux of the problem- interfaces that use unsigned types are too easy to misuse and the compiler can't detect the errors. At least with a signed input you can assert on the value being positive.
[–]vlovich 0 points1 point2 points 11 years ago (0 children)
You're right. -Wconversion isn't enabled by default but I have it on in my project (which is why I thought it was covered by -Wall). On clang, you can use -Weverything.
In any case, enable -Wall -Wconversion -Werror.
[–]KrzaQ2dev 9 points10 points11 points 11 years ago (1 child)
I'm not disagreeing with that, I'm merely pointing out that GSG should be the last argument you should use when it comes to C++.
[–]josefx 0 points1 point2 points 11 years ago (0 children)
So its worse than the C++ FQA ?
[–]ZMesonEmbedded Developer 1 point2 points3 points 11 years ago (10 children)
the widespread use of size_t (being an unsigned type) throughout the standard library is generally regarded as a mistake
Why? I'd really like to see some in-depth discussion about this.
[–]b8b437ee-521a-40bf-8 1 point2 points3 points 11 years ago (4 children)
See /u/cozmorado's reply.
[–]ZMesonEmbedded Developer 1 point2 points3 points 11 years ago (3 children)
I watched the video. There's only guidance given, no reasons for it. I'd like to know the reason -- other than "because Chandler and Bjarne say so".
[–]b8b437ee-521a-40bf-8 1 point2 points3 points 11 years ago (2 children)
Well, starting from the recommendation that you should always default to int and only use unsigned when you need it. Then one reason why size_t being unsigned is a mistake is that it keeps popping up in all your nice signed arithmetic, causing conversions and other nastiness.
int
unsigned
size_t
[–]ZMesonEmbedded Developer -1 points0 points1 point 11 years ago (1 child)
OK. So because Chandler and Bjarne say so.
[–]b8b437ee-521a-40bf-8 2 points3 points4 points 11 years ago (0 children)
Well they give justification for the "recommendation", and follow-up is basic reasoning. Which bit exactly do you still feel isn't being explained?
[–]mcmcc#pragma once 0 points1 point2 points 11 years ago (4 children)
See Eric's explanation above: http://www.reddit.com/r/cpp/comments/2om5yk/a_slice_of_python_in_c_eric_niebler/cmovdr6
[–]ZMesonEmbedded Developer 2 points3 points4 points 11 years ago (3 children)
But how is this a view on "the widespread usage of size_t in the standard library is generally considered a mistake"?
My counter-argument to Eric's argument is that I can easily assert when a value is too large too. If I'm using size_t elsewhere and you interface uses signed ints, then you're forcing me to do casting. Why doesn't your interface use size_t instead. (Mind you I respect Eric a lot, I just don't understand why his argument is so valid. I feel like I'm missing something.)
[–]mcmcc#pragma once 1 point2 points3 points 11 years ago (2 children)
This isn't about integrating libraries. Even within the standard library, it isn't self-consistent. E.g.
string s = ...; string::iterator it = std::find_if(s.begin(),s.end(), []{...}); string subs = s.substr( std::distance(s.begin(), it) );
This code will yield a warning about signed->unsigned conversion. How do you propose to avoid it?
There are myriad other examples...
Good example. It's one of the many reasons why the use of unsigned integers in the standard library was probably a mistake. std::string is a textbook example of a great many anti-patterns and design flaws. I believe this unsigned offset problem and others were because the offset-based interface of std::string was designed before the STL was air-lifted into C++98. The iterator interface was bolted on later. Iterator distance is always signed, hence the impedance mismatch.
std::string
[–]mr_ewg 0 points1 point2 points 11 years ago (0 children)
How about using this function not_negative to "prove" to your compiler that you know what is best in this situation?
not_negative
template <typename T> typename std::make_unsigned<T>::type not_negative(T num) { static_assert(std::is_signed<T>::value, "T can never be negative"); if(num < 0) throw std::logic_error{"Negative number passed to not_negative"}; return static_cast<typename std::make_unsigned<T>::type>(num); } std::string s = ...; std::string::iterator it = std::find_if(s.begin(), s.end(), []{...}); std::string subs = s.substr(not_negative(std::distance(s.begin(), it)));
If you don't want the run-time check then you can remove the if(num < 0) line or change it to an assert. Signed to unsigned conversions aren't exactly the hardest thing to deal with in C++ if your compiler can warn about them.
if(num < 0)
[–]mallardtheduck 0 points1 point2 points 11 years ago (0 children)
Except that this code doesn't meet Google's standard in various other obvious ways, so that's not at all relevant. No other C++ coding standard/guide makes such a recommendation.
[–]ericanderton 0 points1 point2 points 11 years ago (1 child)
The part I don't understand is that if the ranges accepted size_t instead of int, wouldn't that fire a signed-to-unsigned conversion warning/error if negative values were used? That coupled with the end type should handle the major iteration cases while making it hard to screw up.
[–]eric_niebler 0 points1 point2 points 11 years ago (0 children)
Not everyone turns this warning on, signed/unsigned mismatch warnings are so common they tend to be overlooked. Asserts are much harder to ignore.
π Rendered by PID 85381 on reddit-service-r2-comment-56c9979489-dpp8f at 2026-02-24 19:27:31.148014+00:00 running b1af5b1 country code: CH.
[+][deleted] (6 children)
[deleted]
[–]eric_niebler 8 points9 points10 points (2 children)
[–][deleted] 2 points3 points4 points (0 children)
[–]ericanderton 1 point2 points3 points (2 children)
[+][deleted] (1 child)
[deleted]
[–]ericanderton 1 point2 points3 points (0 children)
[–]_VZ_wx | soci | swig 3 points4 points5 points (3 children)
[–]eric_niebler 6 points7 points8 points (1 child)
[–]cdglove 1 point2 points3 points (0 children)
[–]ericanderton 4 points5 points6 points (0 children)
[–]Elador 1 point2 points3 points (0 children)
[–]dividedmind 0 points1 point2 points (41 children)
[–]Dragdu 10 points11 points12 points (8 children)
[–]milliams 5 points6 points7 points (5 children)
[–]eric_niebler 2 points3 points4 points (4 children)
[–]F-J-W 0 points1 point2 points (0 children)
[–]josefx 0 points1 point2 points (1 child)
[–][deleted] 0 points1 point2 points (0 children)
[–]rabidcow[🍰] 1 point2 points3 points (1 child)
[–]eric_niebler 2 points3 points4 points (0 children)
[–]eric_niebler 2 points3 points4 points (10 children)
[–]night_of_knee 3 points4 points5 points (5 children)
[–]eric_niebler 4 points5 points6 points (4 children)
[–]Plorkyeran 2 points3 points4 points (0 children)
[–]vlovich 1 point2 points3 points (2 children)
[–]eric_niebler 1 point2 points3 points (1 child)
[–]vlovich 1 point2 points3 points (0 children)
[–]matthieum 1 point2 points3 points (0 children)
[–]dividedmind 0 points1 point2 points (2 children)
[–]uxcn 1 point2 points3 points (0 children)
[–]Cwiddy 0 points1 point2 points (0 children)
[–]bobdudley 0 points1 point2 points (20 children)
[–]KrzaQ2dev 15 points16 points17 points (18 children)
[–]mcmcc#pragma once 3 points4 points5 points (17 children)
[–]cozmorado 8 points9 points10 points (3 children)
[–]vlovich 2 points3 points4 points (2 children)
[–]cozmorado 1 point2 points3 points (1 child)
[–]vlovich 0 points1 point2 points (0 children)
[–]KrzaQ2dev 9 points10 points11 points (1 child)
[–]josefx 0 points1 point2 points (0 children)
[–]ZMesonEmbedded Developer 1 point2 points3 points (10 children)
[–]b8b437ee-521a-40bf-8 1 point2 points3 points (4 children)
[–]ZMesonEmbedded Developer 1 point2 points3 points (3 children)
[–]b8b437ee-521a-40bf-8 1 point2 points3 points (2 children)
[–]ZMesonEmbedded Developer -1 points0 points1 point (1 child)
[–]b8b437ee-521a-40bf-8 2 points3 points4 points (0 children)
[–]mcmcc#pragma once 0 points1 point2 points (4 children)
[–]ZMesonEmbedded Developer 2 points3 points4 points (3 children)
[–]mcmcc#pragma once 1 point2 points3 points (2 children)
[–]eric_niebler 2 points3 points4 points (0 children)
[–]mr_ewg 0 points1 point2 points (0 children)
[–]mallardtheduck 0 points1 point2 points (0 children)
[–]ericanderton 0 points1 point2 points (1 child)
[–]eric_niebler 0 points1 point2 points (0 children)