Home > Software engineering >  Numeric UDL operator template
Numeric UDL operator template

Time:02-11

I'm trying to define what Pablo Halpern calls a numeric UDL operator template. I want it to return a lambda that would count how many characters at the beginning of a char array are from the given set.

Here's my test code:

template <char... c>
constexpr auto operator ""_cntany() {
  return [](const char* s){
    unsigned n = 0;
    while (((*s==c) || ...)) {   n;   s; }
    return n;
  };
}

int main(int argc, char** argv) {
  return ("test"_cntany)(argv[1]);
}

But this doesn't compile with GCC 11.2 (https://godbolt.org/z/TdbKzTMW8). Here's the error I'm getting:

<source>: In function 'int main(int, char**)':
<source>:11:15: error: no matching function for call to 'operator""_cntany<"test">()'
  11 |       return ("test"_cntany)(argv[1]);
      |               ^~~~~~~~~~~~~
<source>:2:20: note: candidate: 'template<char ...c> constexpr auto operator""_cntany()'
    2 |     constexpr auto operator ""_cntany() {
      |                    ^~~~~~~~
<source>:2:20: note:   template argument deduction/substitution failed:
<source>:11:15: error: '"test"' is not a valid template argument for type 'char' because string literals can never be used in this context
  11 |       return ("test"_cntany)(argv[1]);
     |               ^~~~~~~~~~~~~
Compiler returned: 1

What am I doing wrong?

CodePudding user response:

C doesn't have udl for string with that template format unfortunately.

gcc has an extension for that template <typename Char, Char... c>

so it would be

template <typename Char, Char... c>
constexpr auto operator ""_cntany() {
  return [](const char* s){
    unsigned n = 0;
    while (((*s==c) || ...)) {   n;   s; }
    return n;
  };
}

but it is not portable as extension.

CodePudding user response:

cppreference says

If the literal operator is a template, it must have an empty parameter list and can have only one template parameter, which must be a non-type template parameter pack with element type char (in which case it is known as a numeric literal operator template)

template <char...> double operator "" _x();

Also see [over.literal.5]

i.e. it's numeric-, and not a string literal.

It can be used like 123_cntany.

Note, there is a new C 20 string literal operator template: see this answer

CodePudding user response:

template user-defined literals need to accept numeric values such as 0123_cntany, so you may need to just use user-defined string-literal:

#include <cstddef>
#include <string_view>

constexpr auto operator ""_cntany(const char* s, std::size_t count) {
  return [sv = std::string_view(s, count)](const char* s){
    unsigned n = 0;
    while (sv.contains(*s)) {   n;   s; }
    return n;
  };
}
  • Related