I was just trying to hack up a binary literal operator ""_b
, but got stuck trying to terminate the recursion. How to define a function which can be called using an empty explicit template parameter list, which doesn't conflict with a parameter pack overload? Then, inspiration: match the empty pack expansion to something wacky.
But GCC complains that the nonexistent types of the empty argument list don't agree with not-explicitly-required types of the parameter list. Is it supposed to work this way?
template< char head, char ... tail >
constexpr unsigned long long parse_binary() {
return ( ( head - '0' ) << sizeof ... (tail) )
+ parse_binary< tail ... >(); // Error: no overload for termination.
}
template< typename = void > // I want this to match an empty pack of chars.
// template< short = 0 > // even this would do.
constexpr unsigned long long parse_binary() {
return 0;
}
template< char ... digits >
constexpr unsigned long long operator ""_b() {
return parse_binary< digits ... >();
}
#include <iostream>
int main() {
std::cout << 010101_b << '\n';
}
Note: The question isn't implementing operator ""_b
. That problem can be solved by expanding the pack into the parameter list, and passing std::integral_constant
types around.
Note 2: This code actually does work with a minor adjustment; see my answer below. But that doesn't directly address the question. Hmm, maybe I should have edited this instead of answering…
Wouldn't it be better to terminate the recursion at one character?
template<char Ch>
constexpr unsigned long long parse_binary(){
return Ch - '0';
};
// second head to disambiguate
template< char head1, char head2, char ... tail >
constexpr unsigned long long parse_binary() {
return ( ( head1 - '0' ) << sizeof ... (tail)+1 ) + parse_binary< head2, tail ... >();
}
In any case, the problem is that parse_binary
for zero chars needs to be declared before the variadic version, as Clang nicely points out:
error: call to function 'parse_binary' that is neither visible in
the template definition nor found by argument-dependent lookup
// call trace...
note: 'parse_binary' should be declared prior to the call site
constexpr unsigned long long parse_binary() {
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