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?
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'.
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.
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.
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
andE
, 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With