Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do user-defined string literals and integer literals have different behavior?

Tags:

I'm learning about user-defined literals, and confused with the following test code:

std::chrono::seconds operator"" _s(unsigned long long s) {     return std::chrono::seconds(s); }  std::string operator"" _str(const char *s, std::size_t len) {     return std::string(s, len); }  int main() {     auto str = "xxxxx"_str;     std::cout << str.size() << std::endl;    // works      auto sec = 4_s;     std::cout << sec.count() << std::endl;   // works      std::cout << "xxxxx"_str.size() << std::endl;   // works      std::cout << 4_s.count() << std::endl;   // does **NOT** work!      return 0; } 

The compiler gives the following error message:

error: no matching literal operator for call to 'operator""_s.count' with argument of type 'unsigned long long' or 'const char *', and no matching literal operator template
cout << 4_s.count() << endl;

It seems that it takes _s.count as a user-defined literal. Also, a floating-point literal behaves like an integer literal.

Why do user-defined integer literals and string literals have different behavior?

like image 808
for_stack Avatar asked Nov 24 '17 06:11

for_stack


People also ask

What is a literal What are the different types of literals?

Literal is the word used to describe the value that appears in the source code as opposed to a variable. A literal is a source code representation of a specific data value. For example, the literals in Java include the integer literal 3, the floating-point literal 1.1f, and the character literal 'a'.

How is an integer literal different than a floating point literal?

Integer literals represent fixed integer values like 900, 12, 400, -222 etc. (with in the integer range). Whereas, floating point literals represents fractional values i.e. numbers with decimal values like 25.53, 45.66, 58.66 etc. while writing these literals we should use the notation f or F as 25.53.

Why are string literals used?

A "string literal" is a sequence of characters from the source character set enclosed in double quotation marks (" "). String literals are used to represent a sequence of characters which, taken together, form a null-terminated string.


1 Answers

That's how floating point literals work!!

Add a pair of parentheses and it should work:

std::cout << (4_s).count(); 

Or alternatively, separate them (to stop the compiler from interpreting it as an ill-formed fractional constant floating point literal):

std::cout << 4_s .count(); //              ^ Space here! 

Reference: CppReference.com

In the Notes section of the reference above,

Due to maximal munch, user-defined integer and floating point literals ending in [p, P, (since C++17)] e and E, when followed by the operators + or -, must be separated from the operator with whitespace in the source:

long double operator""_E(long double); long double operator""_a(long double); int operator""_p(unsigned long long);  auto x = 1.0_E+2.0;  // error auto y = 1.0_a+2.0;  // OK auto z = 1.0_E +2.0; // OK auto w = 1_p+2;      // error auto u = 1_p +2;     // OK 

So when it comes to dot, which is used as decimal point, it must be separated from anything behind, or it'll be treated as part of the floating point number.

I have tested the example above from CppReference and got a very similar error message:

test.cpp:19:10: error: unable to find numeric literal operator 'operator""_E+2.0'                     ^^^^^^  auto x = 1.0_E+2.0;  // error 

Got the point how _E+2.0 is considered as a whole ud-suffix?


My original explanation attempt can be found in the revision history of this post.

like image 140
iBug Avatar answered Sep 22 '22 15:09

iBug