147

C++11 introduces user-defined literals which will allow the introduction of new literal syntax based on existing literals (int, hex, string, float) so that any type will be able to have a literal presentation.

Examples:

// imaginary numbers
std::complex<long double> operator "" _i(long double d) // cooked form
{ 
    return std::complex<long double>(0, d); 
}
auto val = 3.14_i; // val = complex<long double>(0, 3.14)

// binary values
int operator "" _B(const char*); // raw form
int answer = 101010_B; // answer = 42

// std::string
std::string operator "" _s(const char* str, size_t /*length*/) 
{ 
    return std::string(str); 
}

auto hi = "hello"_s + " world"; // + works, "hello"_s is a string not a pointer

// units
assert(1_kg == 2.2_lb); // give or take 0.00462262 pounds

At first glance this looks very cool but I'm wondering how applicable it really is, when I tried to think of having the suffixes _AD and _BC create dates I found that it's problematic due to operator order. 1974/01/06_AD would first evaluate 1974/01 (as plain ints) and only later the 06_AD (to say nothing of August and September having to be written without the 0 for octal reasons). This can be worked around by having the syntax be 1974-1/6_AD so that the operator evaluation order works but it's clunky.

So what my question boils down to is this, do you feel this feature will justify itself? What other literals would you like to define that will make your C++ code more readable?


Updated syntax to fit the final draft on June 2011

hichris123
  • 10,145
  • 15
  • 56
  • 70
Motti
  • 110,860
  • 49
  • 189
  • 262
  • 80
    @DeadMG, if you have a problem wit the title you can edit it. It's a bit funny trying to close a 3 year old question that has 11 upvotes and 8 favourites. (Not the mention that the etiquette on this site has changed in the last 3 years). – Motti Jun 28 '11 at 19:40
  • 6
    I think you have an error in your examples: `string operator "" _s(const char*s);"` can not be used to parse `"hello"_s"`. This is a string literal and will look for the operator with an additional `size_t` parameter. Am I right? – towi Oct 11 '11 at 07:01
  • @towi, you're right. I'll update the question (I think this is a change in the standard from when I wrote the question but I can't be sure). – Motti Oct 11 '11 at 09:25
  • 1
    One thing I've wondered about is whether it would make sense to write "portable C" in C++, replacing types like `uint16_t` whose behavior is implementation-dependent, with similar types `uwrap16` and `unum16` whose behavior would be implementation-independent, such that given `uwrap16 w=1; unum16 n=1;` the expressions `w-2` and `n-2` would yield `(uwrap16)65535` and `(int)-1`, respectively [`uint16_t` would yield the first result on systems where `int` is 16 bits, and the second on systems where `int` is larger]. The biggest problem I saw was handling numeric literals. – supercat May 01 '15 at 17:31
  • 1
    Being able to have numeric literals interoperate smoothly with other defined-behavior numeric types would seem like it should allow such types to be used to create a language where code that wanted to perform implementation-dependent actions could do so without having to rely upon implementation-defined behaviors. There are a few places where IDB will still be unavoidable because things like pointer differences and `sizeof` return implementation-dependent integer types, but the situation could still be made a lot better than it is. What would you think of that concept? – supercat May 01 '15 at 17:41
  • @supercat that sounds like a very nice idea – Motti May 02 '15 at 19:56

12 Answers12

199

At first sight, it seems to be simple syntactic sugar.

But when looking deeper, we see it's more than syntactic sugar, as it extends the C++ user's options to create user-defined types that behave exactly like distinct built-in types. In this, this little "bonus" is a very interesting C++11 addition to C++.

Do we really need it in C++?

I see few uses in the code I wrote in the past years, but just because I didn't use it in C++ doesn't mean it's not interesting for another C++ developer.

We had used in C++ (and in C, I guess), compiler-defined literals, to type integer numbers as short or long integers, real numbers as float or double (or even long double), and character strings as normal or wide chars.

In C++, we had the possibility to create our own types (i.e. classes), with potentially no overhead (inlining, etc.). We had the possibility to add operators to their types, to have them behave like similar built-in types, which enables C++ developers to use matrices and complex numbers as naturally as they would have if these have been added to the language itself. We can even add cast operators (which is usually a bad idea, but sometimes, it's just the right solution).

We still missed one thing to have user-types behave as built-in types: user-defined literals.

So, I guess it's a natural evolution for the language, but to be as complete as possible: "If you want to create a type, and you want it to behave as much possible as a built-in types, here are the tools..."

I'd guess it's very similar to .NET's decision to make every primitive a struct, including booleans, integers, etc., and have all structs derive from Object. This decision alone puts .NET far beyond Java's reach when working with primitives, no matter how much boxing/unboxing hacks Java will add to its specification.

Do YOU really need it in C++?

This question is for YOU to answer. Not Bjarne Stroustrup. Not Herb Sutter. Not whatever member of C++ standard committee. This is why you have the choice in C++, and they won't restrict a useful notation to built-in types alone.

If you need it, then it is a welcome addition. If you don't, well... Don't use it. It will cost you nothing.

Welcome to C++, the language where features are optional.

Bloated??? Show me your complexes!!!

There is a difference between bloated and complex (pun intended).

Like shown by Niels at What new capabilities do user-defined literals add to C++?, being able to write a complex number is one of the two features added "recently" to C and C++:

// C89:
MyComplex z1 = { 1, 2 } ;

// C99: You'll note I is a macro, which can lead
// to very interesting situations...
double complex z1 = 1 + 2*I;

// C++:
std::complex<double> z1(1, 2) ;

// C++11: You'll note that "i" won't ever bother
// you elsewhere
std::complex<double> z1 = 1 + 2_i ;

Now, both C99 "double complex" type and C++ "std::complex" type are able to be multiplied, added, subtracted, etc., using operator overloading.

But in C99, they just added another type as a built-in type, and built-in operator overloading support. And they added another built-in literal feature.

In C++, they just used existing features of the language, saw that the literal feature was a natural evolution of the language, and thus added it.

In C, if you need the same notation enhancement for another type, you're out of luck until your lobbying to add your quantum wave functions (or 3D points, or whatever basic type you're using in your field of work) to the C standard as a built-in type succeeds.

In C++11, you just can do it yourself:

Point p = 25_x + 13_y + 3_z ; // 3D point

Is it bloated? No, the need is there, as shown by how both C and C++ complexes need a way to represent their literal complex values.

Is it wrongly designed? No, it's designed as every other C++ feature, with extensibility in mind.

Is it for notation purposes only? No, as it can even add type safety to your code.

For example, let's imagine a CSS oriented code:

css::Font::Size p0 = 12_pt ;       // Ok
css::Font::Size p1 = 50_percent ;  // Ok
css::Font::Size p2 = 15_px ;       // Ok
css::Font::Size p3 = 10_em ;       // Ok
css::Font::Size p4 = 15 ;         // ERROR : Won't compile !

It is then very easy to enforce a strong typing to the assignment of values.

Is is dangerous?

Good question. Can these functions be namespaced? If yes, then Jackpot!

Anyway, like everything, you can kill yourself if a tool is used improperly. C is powerful, and you can shoot your head off if you misuse the C gun. C++ has the C gun, but also the scalpel, the taser, and whatever other tool you'll find in the toolkit. You can misuse the scalpel and bleed yourself to death. Or you can build very elegant and robust code.

So, like every C++ feature, do you really need it? It is the question you must answer before using it in C++. If you don't, it will cost you nothing. But if you do really need it, at least, the language won't let you down.

The date example?

Your error, it seems to me, is that you are mixing operators:

1974/01/06AD
    ^  ^  ^

This can't be avoided, because / being an operator, the compiler must interpret it. And, AFAIK, it is a good thing.

To find a solution for your problem, I would write the literal in some other way. For example:

"1974-01-06"_AD ;   // ISO-like notation
"06/01/1974"_AD ;   // french-date-like notation
"jan 06 1974"_AD ;  // US-date-like notation
19740106_AD ;       // integer-date-like notation

Personally, I would choose the integer and the ISO dates, but it depends on YOUR needs. Which is the whole point of letting the user define its own literal names.

Community
  • 1
  • 1
paercebal
  • 81,378
  • 38
  • 130
  • 159
  • 1
    Thank you, me and my other alternate personalities have been discovered. More seriously, I did write this alone, but perhaps I am using some my native language's expression and they don't translate well into english. – paercebal Oct 30 '08 at 21:39
  • As for the "different parts", as shown by their titles, sorry, I guess this organizes somewhat a quite long post. As for the bold text, it is the summary of the paragraph they are in. People wanting only the info without justification can limit their reading on the titles and bold text. – paercebal Oct 30 '08 at 21:40
  • Thanks for the edit paercebal [I removed my comment about the post being a mess ;o) ] – Motti Nov 02 '08 at 07:22
  • 3
    +1. Really nice explanation. We are waiting for this to be implemented. It is really important for us. We work on MDE (Model-Driven Engineering) and find this a neccesity. I'm adding a response below to explain our case. – Diego Sevilla Oct 27 '10 at 17:26
  • Yeah, now you can write 1+2i, but you still can't write a+bi, so there's absolutely no point. None at all. Just another arcane, opaque (fill in other low frequency adjectives) feature. – TGV Jun 22 '11 at 20:04
  • 10
    @TGV : `you can write 1+2i, but you still can't write a+bi, so there's absolutely no point` : Even ignoring your `a+bi` example is ridiculous, the fact you perceive it as "low frequency" does not mean everyone does. . . Looking at the large picture, the point is to make sure user-defined objects can be as much as possible considered first-class citizens of the language, as are build-in types. So, if you can write `1.5f` and `1000UL`, why couldn't you write `25i` or even `100101b`? To the contrary of C and Java, user types are not to be considered second-class citizen of the language in C++. – paercebal Jun 22 '11 at 20:14
  • I guess the important point from @TGV response might be that UDL feature is for values specified in code. But how many of hardcoded values do you have in your code? Most of data still comes from IO and will use a good old construction way. Though this is true for only some domains and there are domains where hardcoded values are widly used (e.g. UI). – Anton Mar 10 '13 at 09:17
  • 4
    @Anton: `Most of data still comes from IO` : There are a lot of hardcoded values in code. Look at all the booleans, all the integers, all the doubles that come in the code, because it is more convenient to write `x = 2 * y ;` instead of `x = Two * y` where `Two` is a **strongly-typed** constant. The user defined literals enables us to put a type on it, and write: `x = 2_speed * y ;` and have the compiler verify that calculation makes sense. . . It all comes about strong typing. . . Perhaps you won't use it. But I sure will, as soon as I will be able to use a C++11 enabled compiler at work. – paercebal Mar 10 '13 at 21:53
  • `Good question. Can these functions be namespaced? If yes, then Jackpot!` can they? how? – dom0 Dec 02 '13 at 19:54
  • The CSS example using UDLs to act like 'strong typedefs' is fantastic - though a bit far buried in all that text; perhaps you should've come out swinging with a fantastic example to reel in people, rather than risking them losing attention span ;-). One question, though: Don't the usual rule that we cannot use identifiers comprising an underscore followed by an uppercase letter apply equally to UDL suffixes, such as your `_AD`? (This would also mean we couldn't put _any_ UDLs in the global namespace by my understanding, but encouraging moving stuff out of there isn't really a bad thing, so...) – underscore_d Aug 18 '16 at 19:54
  • @dom0 Of course they can, like any other function. The bit you quoted was a rhetorical question, meant to read like 'But what if there's a danger? _If only_ we had _some_ way to disambiguate between names! [winks at audience]'. Since writing my above comment, I've learned that - probably for the reasons I noted above - UDLs **must** be defined at namespace scope. So there you go. – underscore_d Aug 18 '16 at 20:06
  • @underscore_d If you declare it as `operator ""_AD`, without a space between the `""` and the `_AD`, then you never have the identifier `_AD` on its own and never use a reserved name. – Daniel H May 10 '17 at 20:30
  • It is just WRONG to say that if I don't use a language feature, then it doesn't impose a cost. Adding a language feature ALWAYS adds a cost to language users: it is now ANOTHER thing that user "have" to learn. If my resume says that I "know" C++, but the language adds features very fast, then my claim quickly becomes a lie, even though I haven't actually gotten dumber over the years. Yes, there should be an expectation of continuing education, but there is definitely a point where it becomes excessive. UDLs arguably approach that point. That's why Google bans them in their style guide. – allyourcode Dec 26 '21 at 05:10
  • @allyourcode : "it is now ANOTHER thing that user "have" to learn." True, more or less. First, UDLs are not that hard to understand. Second, being a software engineer means learning constantly. Third, you don't need to know all the corners of C++ to truthfully say "I know C++". . . "That's why Google bans them in their style guide" Google's C++ style guide is not a reference, and never has been. We should be very careful in following "style guides" from software houses without context: You never know how much politics/inertia/tech constraints they are hiding, and that don't apply in your case – paercebal Dec 27 '21 at 08:54
  • *"If you don't, well... Don't use it. It will cost you nothing."* Not true. The existence of UDL directly affected the choice for digit separators. Even if I don't use this feature, I still cannot write `1_000_000_000` using underscores as is customary in many other languages. And that is the true cost of features that *someone might like*. – Jeyekomon Feb 08 '22 at 13:50
  • @Jeyekomon : I guess the committee balanced the pros/cons. That is how many C++ developers were willing to sacrifice the potential of writing "1_000_000_000" for some reason (which has always been invalid in C and C++ anyway), in order to have "Hello World"s being a std::string, "Hello World"sv being a std::string_view, or even `45i` being an imaginary number. And the fans of 1_000_000_000 lost the deciding vote. And I'm ok with that. As I am with having the "virtual" keyword in C++ stopping me from using virtual as a variable name as I could have done it in Basic or in C. – paercebal Feb 09 '22 at 18:47
  • 1
    @Jeyekomon but you have been able to write `1'000'000'000` since C++14 – Caleth May 16 '22 at 13:49
73

Here's a case where there is an advantage to using user-defined literals instead of a constructor call:

#include <bitset>
#include <iostream>

template<char... Bits>
  struct checkbits
  {
    static const bool valid = false;
  };

template<char High, char... Bits>
  struct checkbits<High, Bits...>
  {
    static const bool valid = (High == '0' || High == '1')
                   && checkbits<Bits...>::valid;
  };

template<char High>
  struct checkbits<High>
  {
    static const bool valid = (High == '0' || High == '1');
  };

template<char... Bits>
  inline constexpr std::bitset<sizeof...(Bits)>
  operator"" _bits() noexcept
  {
    static_assert(checkbits<Bits...>::valid, "invalid digit in binary string");
    return std::bitset<sizeof...(Bits)>((char []){Bits..., '\0'});
  }

int
main()
{
  auto bits = 0101010101010101010101010101010101010101010101010101010101010101_bits;
  std::cout << bits << std::endl;
  std::cout << "size = " << bits.size() << std::endl;
  std::cout << "count = " << bits.count() << std::endl;
  std::cout << "value = " << bits.to_ullong() << std::endl;

  //  This triggers the static_assert at compile time.
  auto badbits = 2101010101010101010101010101010101010101010101010101010101010101_bits;

  //  This throws at run time.
  std::bitset<64> badbits2("2101010101010101010101010101010101010101010101010101010101010101_bits");
}

The advantage is that a run-time exception is converted to a compile-time error. You couldn't add the static assert to the bitset ctor taking a string (at least not without string template arguments).

R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
emsr
  • 15,539
  • 6
  • 49
  • 62
  • 9
    You could do the same thing by giving std::bitset a proper constexpr constructor. – Nicol Bolas Mar 09 '13 at 03:32
  • 1
    @NicolBolas You're right. I'm actually surprised one isn't in there. Maybe we should propose one or two for 2014 if it isn't too late. – emsr Mar 10 '13 at 00:26
38

It's very nice for mathematical code. Out of my mind I can see the use for the following operators:

deg for degrees. That makes writing absolute angles much more intuitive.

double operator ""_deg(long double d)
{ 
    // returns radians
    return d*M_PI/180; 
}

It can also be used for various fixed point representations (which are still in use in the field of DSP and graphics).

int operator ""_fix(long double d)
{ 
    // returns d as a 1.15.16 fixed point number
    return (int)(d*65536.0f); 
}

These look like nice examples how to use it. They help to make constants in code more readable. It's another tool to make code unreadable as well, but we already have so much tools abuse that one more does not hurt much.

R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
Nils Pipenbrinck
  • 83,631
  • 31
  • 151
  • 221
  • 1
    "but we already have so much tools abuse that *one more does not hurt much.*" Wow, I hope that's not the philosophy behind all that c++[x]1234567890 feature flooding recently. Imagine having to learn a library that uses all of those, plus ten file formats for configuration and two tools for pre and post-processing of you code... – masterxilo May 11 '14 at 02:25
  • @masterxilo Of course, in reality, your example is absurd: UDLs are no more difficult to learn than functions, as just syntax sugar for them - & besides, any good lib only uses features as required to improve UX - & documents exactly what it all means. If someone overuses a feature to generate unreadable code (assuming that's at all avoidable in their line of work...), it doesn't put that feature at fault, just the usage. Plus, one person's unreadable is another's bread-and-butter. It's all opinions - & _options_. If you don't like them, don't worry! You don't _have_ to use them. Others _can_. – underscore_d Aug 18 '16 at 20:02
17

UDLs are namespaced (and can be imported by using declarations/directives, but you cannot explicitly namespace a literal like 3.14std::i), which means there (hopefully) won't be a ton of clashes.

The fact that they can actually be templated (and constexpr'd) means that you can do some pretty powerful stuff with UDLs. Bigint authors will be really happy, as they can finally have arbitrarily large constants, calculated at compile time (via constexpr or templates).

I'm just sad that we won't see a couple useful literals in the standard (from the looks of it), like s for std::string and i for the imaginary unit.

The amount of coding time that will be saved by UDLs is actually not that high, but the readability will be vastly increased and more and more calculations can be shifted to compile-time for faster execution.

coppro
  • 14,338
  • 5
  • 58
  • 73
14

Bjarne Stroustrup talks about UDL's in this C++11 talk, in the first section on type-rich interfaces, around 20 minute mark.

His basic argument for UDLs takes the form of a syllogism:

  1. "Trivial" types, i.e., built-in primitive types, can only catch trivial type errors. Interfaces with richer types allow the type system to catch more kinds of errors.

  2. The kinds of type errors that richly typed code can catch have impact on real code. (He gives the example of the Mars Climate Orbiter, which infamously failed due to a dimensions error in an important constant).

  3. In real code, units are rarely used. People don't use them, because incurring runtime compute or memory overhead to create rich types is too costly, and using pre-existing C++ templated unit code is so notationally ugly that no one uses it. (Empirically, no one uses it, even though the libraries have been around for a decade).

  4. Therefore, in order to get engineers to use units in real code, we needed a device that (1) incurs no runtime overhead and (2) is notationally acceptable.

masonk
  • 9,176
  • 2
  • 47
  • 58
  • Thanks! But what if this doesn't actually cause anyone to use "rich" types? I think the real reason people don't use such libraries is that raw floats is "the path of least resistance". You don't need to "know" anything to use raw floats. Before you can even begin to consider using a "proper" library, you have to have the foresight to ask yourself "Is there a library that understands physical quantities and can do dimensional analysis and such?". Most people don't bother with such "pedantry", despite years of inculcating and admonishments by their school teachers. – allyourcode Dec 26 '21 at 04:59
12

Let me add a little bit of context. For our work, user defined literals is much needed. We work on MDE (Model-Driven Engineering). We want to define models and metamodels in C++. We actually implemented a mapping from Ecore to C++ (EMF4CPP).

The problem comes when being able to define model elements as classes in C++. We are taking the approach of transforming the metamodel (Ecore) to templates with arguments. Arguments of the template are the structural characteristics of types and classes. For example, a class with two int attributes would be something like:

typedef ::ecore::Class< Attribute<int>, Attribute<int> > MyClass;

Hoever, it turns out that every element in a model or metamodel, usually has a name. We would like to write:

typedef ::ecore::Class< "MyClass", Attribute< "x", int>, Attribute<"y", int> > MyClass;

BUT, C++, nor C++0x don't allow this, as strings are prohibited as arguments to templates. You can write the name char by char, but this is admitedly a mess. With proper user-defined literals, we could write something similar. Say we use "_n" to identify model element names (I don't use the exact syntax, just to make an idea):

typedef ::ecore::Class< MyClass_n, Attribute< x_n, int>, Attribute<y_n, int> > MyClass;

Finally, having those definitions as templates helps us a lot to design algorithms for traversing the model elements, model transformations, etc. that are really efficient, because type information, identification, transformations, etc. are determined by the compiler at compile time.

Diego Sevilla
  • 28,636
  • 4
  • 59
  • 87
8

Supporting compile-time dimension checking is the only justification required.

auto force = 2_N; 
auto dx = 2_m; 
auto energy = force * dx; 

assert(energy == 4_J); 

See for example PhysUnits-CT-Cpp11, a small C++11, C++14 header-only library for compile-time dimensional analysis and unit/quantity manipulation and conversion. Simpler than Boost.Units, does support unit symbol literals such as m, g, s, metric prefixes such as m, k, M, only depends on standard C++ library, SI-only, integral powers of dimensions.

Martin Moene
  • 929
  • 11
  • 18
  • Or see [units](https://github.com/nholthaus/units), a compile-time, header-only, dimensional analysis and unit conversion library built on c++14 with no dependencies by [Nic Holthaus](https://github.com/nholthaus). – Martin Moene Sep 29 '16 at 05:56
  • I don't think you need UDLs for dimensional analysis though. E.g. auto force = Newtons(2); UDLs just make your code a little prettier at the cost of requiring everyone to learn more features of C++. I believe this is why the Google C++ style guide bans UDLs (or at least it did a few years ago; I might be out of date on that). – allyourcode Dec 26 '21 at 04:49
6

Hmm... I have not thought about this feature yet. Your sample was well thought out and is certainly interesting. C++ is very powerful as it is now, but unfortunately the syntax used in pieces of code you read is at times overly complex. Readability is, if not all, then at least much. And such a feature would be geared for more readability. If I take your last example

assert(1_kg == 2.2_lb); // give or take 0.00462262 pounds

... I wonder how you'd express that today. You'd have a KG and a LB class and you'd compare implicit objects:

assert(KG(1.0f) == LB(2.2f));

And that would do as well. With types that have longer names or types that you have no hopes of having such a nice constructor for sans writing an adapter, it might be a nice addition for on-the-fly implicit object creation and initialization. On the other hand, you can already create and initialize objects using methods, too.

But I agree with Nils on mathematics. C and C++ trigonometry functions for example require input in radians. I think in degrees though, so a very short implicit conversion like Nils posted is very nice.

Ultimately, it's going to be syntactic sugar however, but it will have a slight effect on readability. And it will probably be easier to write some expressions too (sin(180.0deg) is easier to write than sin(deg(180.0)). And then there will be people who abuse the concept. But then, language-abusive people should use very restrictive languages rather than something as expressive as C++.

Ah, my post says basically nothing except: it's going to be okay, the impact won't be too big. Let's not worry. :-)

mstrobl
  • 2,381
  • 14
  • 16
3

I have never needed or wanted this feature (but this could be the Blub effect). My knee jerk reaction is that it's lame, and likely to appeal to the same people who think that it's cool to overload operator+ for any operation which could remotely be construed as adding.

fizzer
  • 13,551
  • 9
  • 39
  • 61
2

C++ is usually very strict about the syntax used - barring the preprocessor there is not much you can use to define a custom syntax/grammar. E.g. we can overload existing operatos, but we cannot define new ones - IMO this is very much in tune with the spirit of C++.

I don't mind some ways for more customized source code - but the point chosen seems very isolated to me, which confuses me most.

Even intended use may make it much harder to read source code: an single letter may have vast-reaching side effects that in no way can be identified from the context. With symmetry to u, l and f, most developers will choose single letters.

This may also turn scoping into a problem, using single letters in global namespace will probably be considered bad practice, and the tools that are supposed mixing libraries easier (namespaces and descriptive identifiers) will probably defeat its purpose.

I see some merit in combination with "auto", also in combination with a unit library like boost units, but not enough to merit this adition.

I wonder, however, what clever ideas we come up with.

peterchen
  • 40,917
  • 20
  • 104
  • 186
  • 1
    `using single letters in global namespace will probably be considered bad practice` But that has no relevance: (A) UDLs must be defined at (non-global) namespace scope... presumably because (B) they must consist of an underscore then >=1 letter, not just the letter, and such identifiers in the global NS are reserved for the implementation. That's at least 2 points against the idea that UDLs innately generate confusion. As for having to scope namespace reducing the utility of the feature, that's why e.g. the stdlib declares them in `inline namespace`s that users can import wholesale if desired. – underscore_d Aug 18 '16 at 20:08
2

I used user literals for binary strings like this:

 "asd\0\0\0\1"_b

using std::string(str, n) constructor so that \0 wouldn't cut the string in half. (The project does a lot of work with various file formats.)

This was helpful also when I ditched std::string in favor of a wrapper for std::vector.

rr-
  • 14,303
  • 6
  • 45
  • 67
-5

Line noise in that thing is huge. Also it's horrible to read.

Let me know, did they reason that new syntax addition with any kind of examples? For instance, do they have couple of programs that already use C++0x?

For me, this part:

auto val = 3.14_i

Does not justify this part:

std::complex<double> operator ""_i(long double d) // cooked form
{ 
    return std::complex(0, d);
}

Not even if you'd use the i-syntax in 1000 other lines as well. If you write, you probably write 10000 lines of something else along that as well. Especially when you will still probably write mostly everywhere this:

std::complex<double> val = 3.14i

'auto' -keyword may be justified though, only perhaps. But lets take just C++, because it's better than C++0x in this aspect.

std::complex<double> val = std::complex(0, 3.14);

It's like.. that simple. Even thought all the std and pointy brackets are just lame if you use it about everywhere. I don't start guessing what syntax there's in C++0x for turning std::complex under complex.

complex = std::complex<double>;

That's perhaps something straightforward, but I don't believe it's that simple in C++0x.

typedef std::complex<double> complex;

complex val = std::complex(0, 3.14);

Perhaps? >:)

Anyway, the point is: writing 3.14i instead of std::complex(0, 3.14); does not save you much time in overall except in few super special cases.

R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
Cheery
  • 24,645
  • 16
  • 59
  • 83
  • You'd write ``auto val = 3.14i``. – Mikael Jansson Oct 26 '08 at 12:56
  • What you want for the last part is using std::complex; Then you can do complex val = complex(0, 3.14); I still like auto val = 3.14i; better. – KeithB Oct 26 '08 at 13:39
  • 11
    @Cheery: For you, "auto val = 3.14i" does not justify the code written to support it. I could answer that, for me "printf("%i", 25)" does not justify the code written for printf. Do you see a pattern? – paercebal Oct 26 '08 at 14:31
  • 5
    @Cheery: "Line noise in that thing is huge". No, it isn't... "Also it's horrible to read". Your subjective argument is interesting, but you should take a look at operator overloading in general to see the the code for this feature is far from surprising/shocking... For a C++ developer – paercebal Oct 26 '08 at 14:40
  • 3
    auto will help readability. consider using interators in a for loop: for(auto it = vec.begin();it!=vec.end();++it)... I know about for_each, but dislike having to create a functor to use it. – KitsuneYMG Jun 22 '09 at 08:56
  • 1
    @kts: With C++1x we'll have lambda and range for – Joe D Aug 26 '10 at 20:44
  • 3
    If your line of C++ is better than C++0x, then my line is better yet. Write just: `std::complex val(0, 3.14);`. – Ben Voigt Sep 21 '11 at 18:00
  • -1 because I could have saved few moments of my life if I didn't read your pointless argument. – OneOfOne Jan 19 '14 at 19:50
  • @BenVoigt What about the very simple `auto val = 3.14i`. Seems much more sensible that yours, no offense intended. – Miles Rout May 28 '14 at 10:03
  • @KitsuneYMG Or just use a range-based for loop: for (T t : vec) { ... } – Miles Rout May 28 '14 at 10:04
  • @Miles you clearly misunderstood the sarcasm. Also, range based for doesn't replace all iterator usage. What about when you need access to the iterator not just the value? – Ben Voigt May 28 '14 at 12:00