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?
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.