3

I am seeing some behavior I can't quite explain. Consider test.cpp:

#include <iostream>
long double operator"" _N(long double a) { return a; }

int main(int argc, char** argv) {
    long double t = 4.0_N;
}

Issuing

g++ -std=c++11 test.cpp

gives me

test.cpp:2:22: error: expected suffix identifier
long double operator"" _N(long double V) { return V; }
                    ^

Making any of the the following changes will NOT give the error:

// #include <iostream>  // Is there some conflict with something in iostream then?
long double operator"" _N(long double a) { return a; }    
...

#include <iostream>
long double operator"" _P(long double a) { return a; } 
// (or most other letters and/or words) 
...

however, the problem persists for at least _B and _C (I didn't test the entire alphabet)...

What am I missing here?

More info:

$ g++ --version 
g++ (GCC) 4.8.2

Running in CygWin on 64-bit Windows 7 SP1.

Rody Oldenhuis
  • 37,726
  • 7
  • 50
  • 96
  • 6
    Names starting with underscore followed by a capital letter are reserved for the language and library implementation. – R. Martinho Fernandes Apr 29 '14 at 13:13
  • [See this old answer](http://stackoverflow.com/a/228797/440558). – Some programmer dude Apr 29 '14 at 13:13
  • 1
    @R.MartinhoFernandes: hmmm...so "names" includes user-defined literals then? Still seems odd, as the C++11 spec more or less mandates the use of an initial underscore for the names of user-defined literals... *it* says that literals *not* starting with an underscore are reserved for future standardization... – Rody Oldenhuis Apr 29 '14 at 13:18
  • Clang 3.4 compiles your original code just fine. – John Zwinck Apr 29 '14 at 13:20
  • @JohnZwinck: yes, it seems to depend on specific implementations of `iostream`... – Rody Oldenhuis Apr 29 '14 at 13:21
  • Can you try running it through the preprocessor only and show us what that gives? g++ -E or so. – John Zwinck Apr 29 '14 at 13:21
  • 1
    Unfortunately, yes, because those identifiers starting with underscore-uppercase are meant for macros (think stuff like `_WIN32`) and those get expanded everywhere :( The reason the UDLs are required to start with underscore is consistency: the language already uses non-underscored suffixes (`f`, `l`, `u`, etc) so they decided to reserve the non-underscored UDL names. So in effect UDLs have to start with underscore + non-uppercase. – R. Martinho Fernandes Apr 29 '14 at 13:22
  • @R.MartinhoFernandes: that's really quite unfortunate...So this is also not something a namespace will be able to resolve (i.e., capture the UDL def in a namespace)? – Rody Oldenhuis Apr 29 '14 at 13:27
  • @JohnZwinck: [here ya go](http://pastebin.com/USSiRcGQ) – Rody Oldenhuis Apr 29 '14 at 13:28
  • 1
    @R.MartinhoFernandes [not exactly a dup](http://stackoverflow.com/questions/12721584/user-defined-literals-underscores-and-global-names) but relevant. – Shafik Yaghmour Apr 29 '14 at 13:40

1 Answers1

3

With the preprocessed output you posted (http://pastebin.com/USSiRcGQ) we can see the problem right away:

long double operator "" 04(long double V) { return V; }

So you have some header file which does (the equivalent of) this:

#define _N 04

It would be interesting to know which header that is--you can try grep -rw _N /usr/include and see if it pops up.

Now that you know this, if you're brave I guess you could #undef _N, but really you should change to a suffix like _n or maybe something more descriptive.

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • Got it: `/usr/include/ctype.h` – Rody Oldenhuis Apr 29 '14 at 13:34
  • Yup, I see it back in GCC 4.2 as well: http://www.filewatcher.com/p/arm-rtems-gcc-4.2.0_1.tbz.42779445/arm-rtems/include/ctype.h.html – John Zwinck Apr 29 '14 at 13:34
  • Well, "descriptive" depends on context. I was trying to write a strong-typed system for physics units (see [this question](http://stackoverflow.com/questions/15196955/)), where `Force P = 4.8_N;` would indicate a force of 4.8 Newtons (capital `N` is the [SI-standard symbol](http://en.wikipedia.org/wiki/International_System_of_Units) for Newtons). And lower-case `n` would be confusing, because that is the SI-standard notation for the "nano"-multiplier...Guess I'll have to live with some other notation. – Rody Oldenhuis Apr 29 '14 at 13:38
  • Well your system itself could use a prefix within the suffix, like _zN for Newtons etc. Single characters rarely make good identifiers in code anyway, even though they do make sense in written math/physics/etc. – John Zwinck Apr 29 '14 at 13:41
  • 1
    17.6.4.3.2 Certain sets of names and function signatures are always reserved to the implementation: — Each name that contains a double underscore __ or begins with an underscore followed by an uppercase letter is reserved to the implementation for any use. — Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace. – Graznarak Apr 29 '14 at 14:30