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…
No official word on the compliance of such tricky matching, but the given code does work if the two overloads are transposed.
The second, terminating overload is not visible to the first because the first resolves the name at template-definition time. Only function calls dependent on a template parameter have lookup deferred until instantiation time.
Just to be clear, this works: