I want to limit a variadic function to a certain number of inputs - say, two. For that, this works fine in my environment (VS2017, C++17):
#include <type_traits>
template<typename... T>
auto f(T...) -> typename std::enable_if<sizeof...(T) == 2>::type {
// no-op
}
int main() {
// f(1); // should fail
f(1,2);
// f(1,2,3); // should fail
}
But if I introduce an alias template, it doesn't.
#include <type_traits>
template<typename... T>
using two_params = typename std::enable_if<sizeof...(T) == 2>::type;
template<typename... T>
auto f(T...) -> two_params<T...> { // failed to specialize alias template
}
int main() {
// f(1); // should fail
f(1,2);
// f(1,2,3); // should fail
}
Interestingly, if I change the condition to 1
or the actual desired number of inputs, the substitution is successful.
// This works, except that it permits a single argument even when it shouldn't.
// Both conditions ||'d together seems to be needed in the general case.
template<typename... T>
using two_params = typename std::enable_if<sizeof...(T) == 1 || sizeof...(T) == 2>::type;
It seems that f(1,2)
generates two values of sizeof...(T)
. What exactly is going on here?
Some references I've looked at:
- sizeof...
- alias template
- parameter pack
- Pack expansion for alias template (similar problem)