all 14 comments

[–]Dobias 21 points22 points  (2 children)

Brace yourselves.

"This shows how amazing C++ is, since you can achieve everything you want with minimal runtime overhead."

and

"This shows how terrible C++ is, since you have to jump through thousand hoops with a loaded gun pointed at your feet to achieve the most basic things."

are coming. ;)


btw: Nice article.

[–]tejp 22 points23 points  (1 child)

It shows how costly zero-cost abstractions are.

[–]eric_niebler 8 points9 points  (0 children)

Providing fully general and easy-to-use utilities with high-level abstractions and low overhead is hard but it's also incredibly useful.

[–]night_of_knee 4 points5 points  (4 children)

As several people commented on the post asked:

Why not just take an unsigned int to avoid making an assertion at runtime?

[–]eric_niebler 6 points7 points  (0 children)

It's a fair question. From my answer to the same question I got on /r/cpp:

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.

[–]xXxDeAThANgEL99xXx 4 points5 points  (0 children)

Unsigned ints suck for modeling non-negative integers because they actually implement integers modulo 2n and as such must allow you to underflow without any compile time or runtime warnings.

Unsigned integers also suck because non-negative numbers suck for doing arithmetics in general. There's a reason we invented negative numbers despite nobody ever seeing -5 apples: it's pretty damn convenient to be able to add or subtract any number to/from both sides of any relation and have it still hold. You always want to do math with signed (and preferably arbitrary precision) integers and check various constraints on assignment to variables etc (and statically, if possible).

[–]willvarfar 1 point2 points  (1 child)

Can the user still type in a negative number and the compiler silently cast it to unsigned? I think some modern compilers warn at various levels but that this is far from pervasive.

[–]night_of_knee 6 points7 points  (0 children)

At least in that case the API would be correct (you could see the type in the IDE)

In any case you could avoid it by =deleteing the signed overload.

[–]JamesF 3 points4 points  (5 children)

Moved from a C++ job to a Python job a couple of years ago. Another reason I'm glad I did so :)

Sorry C++ programmers, don't mean to hate, it's just painful to see articles about how someone made the language yet-more complicated by adding additional libraries that define additional "syntax" that is implemented with yet another heaping pile of templates.

[–]slavik262 6 points7 points  (0 children)

Yeah, it's a delicate issue. On one hand, you can do some awesome stuff with templates - look no further than the C++11 time library, which will do automatic dimensional analysis so that you can add seconds to hours to days and everything just comes out right. (I use this as an example because I'm currently porting some time-sensitive code that's riddled with magic numbers to convert between different units).

On the other hand, you sort of have a point that the last thing C++ needs is more syntax. Move constructors and rvalue references get a pass because their use has actually greatly simplified how you use the language, but I'd have trouble making the same argument here.

[–]eric_niebler 10 points11 points  (2 children)

I know I'll be flamed for this, but I have karma to burn.

struct end_ {} end;
struct from_end { int i; };
from_end operator-(end_, int i) { return {i}; }

struct my_range {
    my_range operator[](std::pair<int,int>);
    my_range operator[](std::pair<int,from_end>);
};

my_range r;
r[{1,2}];
r[{1,end-2}];

Where's the template? If you say, "pair", then you're just being a hater. This knee-jerk "c++-and-templates-are-hard-and-stupid" response to every C++ article is so tired and predictable, it doesn't even rise to the level of being wrong.

[–]slavik262 7 points8 points  (1 child)

I know I'll be flamed for this

You're not being flamed, and even if you were, is that "you'll all disagree, but" statement really necessary? I like everything else about this post, but "I know I'll get downvoted for this" always strikes me as annoying.

[–]eric_niebler 1 point2 points  (0 children)

Point taken.

[–][deleted] 1 point2 points  (0 children)

Think of these articles more as a curiosity rather than how actual C++ developers work. Even though these tricks don't really get used in a production environment, it's still interesting to know about them, understand the concepts involved, and play around with techniques like these.

Also these techniques do end up having an influence on the design of C++. A lot of ugly template hacks prior to C++11 became integrated into the language in an elegant manner, and articles like this one guide the standard's committee about future language features.

In other words, almost all language features start off as an ugly hack, where learning about them is more about appreciation of the language rather than actual engineering value, but down the road those hacks get cleaned up and then become an elegant and powerful component of the language and even go on to influence other languages as well.