
Literal operator templates for strings
The C ++ 11 standard introduced such a thing as user literals into the language [1] . Specifically, a dozen options for defining the operator "" , adding a little syntactic sugar, all, with the exception of one - a template variant:
This option differs in that it not only gives an alternative option for calling a function using a suffix, but allows you to define your own rules for parsing the passed argument at the compilation stage, thereby expanding the capabilities of the compiler.
For instance:
However, there was a slight omission in the development of the standard - the template version of the user literal allows you to work only with numeric arguments, despite the fact that they are parsed character-by-character.
Such an omission, of course, could not have remained unnoticed, and at the stage of approval of the C ++ 14 standard, a solution was proposed for string arguments [2]
It was soon implemented in GCC [3] and clang (GNU extension) compilers . However, the final edition of the C ++ 14 standard did not make it. However, let's not despair, there is hope that C ++ 17 will please us. In the meantime, let's see how it will be possible to apply a new type of user literals.
Define a meta-string template:
Define our meta-string literal generator:
Create a map-like template for a data structure, with types as keys:
Since we are going to use meta strings as key types, we add a bit of input / output:
Well, now the example itself:
We can also inherit by adding new functions:
The resulting objects statically infer the type of the field by the given key. And when using an invalid key, they not only generate a compilation error, but they can also fill in the clang compiler:

template type operator "" _op();
This option differs in that it not only gives an alternative option for calling a function using a suffix, but allows you to define your own rules for parsing the passed argument at the compilation stage, thereby expanding the capabilities of the compiler.
For instance:
auto x = 10001000100011001001001010001000_b;
However, there was a slight omission in the development of the standard - the template version of the user literal allows you to work only with numeric arguments, despite the fact that they are parsed character-by-character.
Such an omission, of course, could not have remained unnoticed, and at the stage of approval of the C ++ 14 standard, a solution was proposed for string arguments [2]
template type operator "" _op();
It was soon implemented in GCC [3] and clang (GNU extension) compilers . However, the final edition of the C ++ 14 standard did not make it. However, let's not despair, there is hope that C ++ 17 will please us. In the meantime, let's see how it will be possible to apply a new type of user literals.
Define a meta-string template:
template
struct str {
static constexpr const char value[sizeof...(Chars)+1] = {Chars...,'\0'};
static constexpr int size = sizeof...(Chars);
};
template
constexpr const char str::value[sizeof...(Chars)+1];
Define our meta-string literal generator:
template
constexpr str operator"" _s()
{
return str();
}
Create a map-like template for a data structure, with types as keys:
template
struct field {
using key = Key;
using type = Type;
type value;
};
template
struct field_by_type;
template
struct field_by_type,Tail...>, N> {
static constexpr int value = N;
};
template
struct field_by_type, N> : field_by_type,N+1> {};
template
struct record {
using tuple_type = std::tuple;
template
typename std::tuple_element::value,tuple_type>::type::type& operator[](Key) {
return std::get::value>(data).value;
}
template
const typename std::tuple_element::value,tuple_type>::type::type& operator[](Key) const {
return std::get::value>(data).value;
}
tuple_type data;
};
Since we are going to use meta strings as key types, we add a bit of input / output:
template
std::ostream& operator<< (std::ostream& os, const field f){
os << Key::value << " = " << f.value << "\n";
return os;
}
template
struct print_tuple {
std::ostream& operator() (std::ostream& os, const std::tuple& t) {
os << std::get(t);
return print_tuple{}(os,t);
}
};
template
struct print_tuple<0, Ts...> {
std::ostream& operator() (std::ostream& os, const std::tuple& t) {
return os;
}
};
template
std::ostream& operator<< (std::ostream& os, const record& r) {
os << "{\n";
print_tuple{}(os,r.data);
os << "}";
return os;
}
Well, now the example itself:
using Person = record<
field,
field,
field
>;
int main(){
Person p;
p["id"_s] = 10;
p["first_name"_s] = "John";
p["last_name"_s] = "Smith";
std::cout << p << "\n";
}
We can also inherit by adding new functions:
class Person
: public record<
field,
field,
field
>
{
public: void set_name(const std::string& f,const std::string& l) {
(*this)["first_name"_s] = f;
(*this)["last_name"_s] = l;
};
};
int main(){
Person p;
p["id"_s] = 10;
p.set_name("John","Smith");
std::cout << p << "\n";
}
The resulting objects statically infer the type of the field by the given key. And when using an invalid key, they not only generate a compilation error, but they can also fill in the clang compiler:

References
- User-defined literals (cppreference)
- N3599 Literal operator templates for strings (Richard Smith)
- [C ++ 1y] Support n3599 - Literal operator templates for strings for C ++ 1y (GCC Project)