What is C++20's string literal operator template? Cppreference's example in this respect is quite concise and not very clear to me:
struct A { A(const char *); auto operator<=>(const A&) const = default; }; template<A a> A operator ""_a();
In trying to understand what this feature is I've just learned that you can have numeric literal operator templates in C++, which make each digit of numerical constant be passed as a non-type argument to a template (cf. a better explanation here). Currently, literal operator templates do not work with character literals, though there are compilers extensions enabling that. I don't think C++20's string literal operator templates have anything to do with that as I've learned that proposals to extend literal operator templates to work with character literals were voted down in the commitee?
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.
A string literal is a sequence of zero or more characters enclosed within single quotation marks. The following are examples of string literals: 'Hello, world!' '10-NOV-91' 'He said, "Take it or leave it."'
A string literal with the prefix L is a wide string literal. A string literal without the prefix L is an ordinary or narrow string literal. The type of narrow string literal is array of char .
There are three sets of literal types available in TypeScript today: strings, numbers, and booleans; by using literal types you can allow an exact value which a string, number, or boolean must have.
There were two separate proposals:
The first proposal was partially merged into the second. String literals still are not valid arguments as non-type template parameters, but they are valid arguments into class types. The example from [temp.arg.nontype]/4 might help:
template<class T, T p> class X { /* ... */ }; X<const char*, "Studebaker"> x; // error: string literal as template-argument const char p[] = "Vivisectionist"; X<const char*, p> y; // OK struct A { constexpr A(const char*) {} friend auto operator<=>(const A&, const A&) = default; }; X<A, "Pyrophoricity"> z; // OK, string literal is a constructor argument to A
However, the part of the first proposal which extended the literal operators was what was merged into the second, [lex.ext]/5:
If S contains a literal operator template with a non-type template parameter for which str is a well-formed template-argument, the literal L is treated as a call of the form
operator "" X<str>()
So using this:
struct A { A(const char *); auto operator<=>(const A&) const = default; }; template<A a> A operator ""_a() { return a; }
We can write "Hello"_a
, which will be interpreted as calling operator "" _a<A("Hello")>
.
Note that these rules are slightly in flux, as the defaulted <=>
requirement will be changing to a defaulted ==
requirement as per P1185.
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