Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

template parameter list for literal operator

Here is my implementation of converting binary literal to decimal:

template<char Head, char... Tail>
constexpr int operator"" _b()
{
    if constexpr (sizeof... (Tail) == 0)
    {
        return Head - '0';
    }
    else
    {
        return (Head - '0') * (1 << sizeof...(Tail)) + operator"" _b<Tail...>();
    }
}

GCC compiles happily,

while Clang fails:

prog.cc:1:2: error: template parameter list for literal operator must be either 'char...' or 'typename T, T...'
        template<char Head, char... Tail>
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
prog.cc:19:27: error: no matching literal operator for call to 'operator""_b' with argument of type 'unsigned long long' or 'const char *', and no matching literal operator template
    std::cout << 110110110_b;
                      ^

icc also fails:

error: a literal operator template must have a template parameter list equivalent to "<char ...>"

    constexpr int operator"" _b()

                  ^

MSVC also fails:

<source>(2): error C3686: 'operator ""_b': literal operator template must have exactly one template parameter that is a parameter pack

So, icc requires char... while clang and msvc require typename T, T... or char..., only gcc allow my Head and Tail.

The workaround should be simple ---- just replace char Head, char... Tail with char... digits and return a new aux function which using char Head, char... Tail as template parameters, or use a struct then specialize head and head, tail... without if constexpr.

But I didn't find related requirement from the standard draft. Can you tell me which one conforms the standard? Of course, if you have more elegant solution(besides the two I mentioned above) which will not invoke the compiler errors, please paste here, I'll very appreicate.

like image 664
Chen Li Avatar asked Dec 15 '18 02:12

Chen Li


People also ask

What are template parameters?

In UML models, template parameters are formal parameters that once bound to actual values, called template arguments, make templates usable model elements. You can use template parameters to create general definitions of particular types of template.

What is a template template parameter in C++?

In C++ this can be achieved using template parameters. A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.

Which parameter is allowed for non-type template?

Which parameter is legal for non-type template? Explanation: The following are legal for non-type template parameters:integral or enumeration type, Pointer to object or pointer to function, Reference to object or reference to function, Pointer to member.

What is the role of parameter in a template?

An identifier that names a non-type template parameter of class type T denotes a static storage duration object of type const T, called a template parameter object, whose value is that of the corresponding template argument after it has been converted to the type of the template parameter.


3 Answers

The standard spells it out pretty explicitly in [over.literal]/5:

The declaration of a literal operator template shall have an empty parameter-declaration-clause and its template-parameter-list shall have a single template-parameter that is a non-type template parameter pack with element type char.

So GCC is wrong in allowing this.

like image 129
Nicol Bolas Avatar answered Nov 15 '22 00:11

Nicol Bolas


I don't know who's right but I propose a C++17 alternative: comma operator and template folding instead of recursion

   template <char ... Chs>
   constexpr int operator"" _b()
    {
      int ret {};

      return ((ret <<= 1, ret += Chs - '0'), ...);
   }
like image 32
max66 Avatar answered Nov 14 '22 22:11

max66


Literal operator template of the form

template <class T, T... >
constexpr int operator "" _b();

is a clang and gcc extension, MSVC don't support that extension.

There was however a proposal to reconsider literal operator templates

like image 26
Jans Avatar answered Nov 14 '22 22:11

Jans