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.
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.
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 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.
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.
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.
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'), ...);
}
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
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