There were two separate proposals:
- Allowing string literals as non-type template parameters (P0424)
- Allowing class types as non-type template parameters (P0732)
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.