6

I'm wondering why I can't write code like this:

constexpr double radius = 27_km.to_miles(); // _km returns Distance instance 
                                            // which has to_miles()

Both GCC 4.8.1 and Clang 3.4 complain that they couldn't find literal operator operator"" _km.to_miles unless I wrap 27_km in parentheses:

constexpr double radius = (27_km).to_miles(); // fine

By my reading of section 2.14.8 of the standard, a UDL suffix can't contain a period, so why are the compilers parsing the code like this? Are they correct or is it a bug?

EDIT: You can see a full example (with different UDL and method names) here: http://ideone.com/rvB1pk

Alex Korban
  • 14,916
  • 5
  • 44
  • 55
  • I didn't even know this feature of C++11, thanks! – orlp Oct 16 '13 at 03:56
  • 1
    Could you show a full example that produces the error? – Jesse Good Oct 16 '13 at 06:17
  • I've added a link to an example. – Alex Korban Oct 16 '13 at 19:59
  • This version compiles on clang++3.4: `30_au .to_light_years();` (note the whitespace) -- which is.. strange. – dyp Oct 16 '13 at 20:04
  • @DyP: same thing with GCC 4.8.1. You can insert spaces like that after a variable name too, so it isn't that strange. – Alex Korban Oct 16 '13 at 23:55
  • 1
    I didn't mean it is strange inserting a whitespace makes it work (I suspected it would work, tried, and succeeded), but it is strange that there's a difference between `30_au.to_light_years()` and `30_au .to_light_years()` [with a whitespace]. I agree with Jerry Coffin's analysis that it's probably a bug. – dyp Oct 16 '13 at 23:57

2 Answers2

3

The suffix for a UDL is supposed to be a normal identifier (with a leading underscore), so it looks like a bug to me.

R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
2

This may be a lexer issue. The user-defined literal is to be tokenized as a single chunk - number plus suffix is one whole token. In the case of numeric literals the characters it is allowed to slurp up includes the decimal '.'. Lookup pp-number: section 2.10 - lex.ppnumber in the latest draft of the standard. Walk through how the preprocessor (lexer) would scan the token:

30_au.to_light_years()

digit
digit
identifier-nondigit
.
identifier-nondigit x 14
( breaks the spell

So the preprocessor sees 30_au.to_light_years as a big freaky (floating-point) number. Then later, during the number parsing phase we see digit, digit, identifier-nondigit... At that point, the remainder from '-' onwards is handed off as a suffix identifier.

Remember that number literals are interpreted after the preprocessor tokenizes.

I think this is actually not a defect.

emsr
  • 15,539
  • 6
  • 49
  • 62
  • After looking at section 2.10 I agree - it doesn't look like a defect, although it is an inconvenience! – Alex Korban Oct 17 '13 at 05:32
  • @AlexKorban: After looking at §2.2/7, I disagree. "The process of analyzing and translating the tokens may occasionally result in one token being replaced by a sequence of other tokens". Starting as a single preprocessor token doesn't mean it stays a single token throughout compilation. – Jerry Coffin Oct 21 '13 at 04:09
  • @JerryCoffin: that note specifically refers to 14.2 ("Names of template specializations"), which appears to be about the disambiguation of >>. So it seems to me emsr's interpretation is still correct. Am I missing something? – Alex Korban Oct 21 '13 at 22:09
  • @AlexKorban: Yes, I think so -- that's giving a reference to one possibility, but does nothing to limit it to that one possibility. – Jerry Coffin Oct 21 '13 at 22:13
  • @JerryCoffin: I guess it could be interpreted like that. I hope you're correct, as it would mean there's a possibility I won't have to wrap literals in parentheses in the future! – Alex Korban Oct 21 '13 at 22:42