Here is an extremely simple code :
template <typename... Args,
typename std::enable_if<std::less<int>()(sizeof...(Args), 3), int>::type* = nullptr>
void test(std::tuple<Args...>)
{
}
int main()
{
test(std::make_tuple(1, 2));
}
It's just simple function template with some enable_if
condition. (for further SFINAE).
But it fails to compile in Visual Studio 2019 with C++ 17 setup.
error C2672: 'test': no matching overloaded function found
error C2783: 'void test(std::tuple<_Types...>)': could not deduce template argument for '__formal'
However I found that it compiles well in GCC and Clang. Why does that seemingly innocent code fail?
funny thing is if I substitute sizeof...(Args)
to 2
then it suddenly works.
Edit : My original question doesn't provide type in enable_if
, but I found that void*
is not allowed as a non-type template parameter in C++ 17. But It doesn't matter. Because even if I change to std::enable_if<std::less<int>()(sizeof...(Args), 3), int>
, it still fails with same error.
Per [comparisons.less]:
template <class T = void> struct less { constexpr bool operator()(const T& x, const T& y) const; };
constexpr bool operator()(const T& x, const T& y) const;
Returns:
x < y
.
The operator is constexpr
. Therefore, your code is fine as far as the less
is concerned.
However, technically speaking, MSVC is actually right here — non-type template parameters shall not have type void*
in C++17. MSVC actually diagnosed that. That's purely a coincidence, anyway.
You can use <
directly as a workaround:
template <typename... Args,
typename std::enable_if<(sizeof...(Args) < 3), int>::type = 0>
void test(std::tuple<Args...>)
(Note that int
is used instead of void*
, so that a language pedant has absolutely nothing to say.)
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