问题描述
这是一个非常简单的代码:
template <typename... Args,typename std::enable_if()(sizeof...(Args), 3), int>::type* = nullptr>无效测试(std::tuple){}int main(){测试(std::make_tuple(1, 2));}
它只是带有一些enable_if
条件的简单函数模板.(进一步 SFINAE).
但是它无法在Visual Studio 2019 with C++ 17设置中编译.
error C2672: 'test': 没有找到匹配的重载函数错误 C2783:void test(std::tuple<_Types...>)":无法推导出__formal"的模板参数
但是我发现它在 GCC 和 Clang 中编译得很好.为什么那个看似无辜的代码会失败?
有趣的是,如果我将 sizeof...(Args)
替换为 2
然后它突然起作用了.
Edit :我最初的问题没有在 enable_if
中提供类型,但我发现 void*
不允许作为非-在 C++ 17 中键入模板参数.但没关系. 因为即使我更改为 std::enable_if<std::less<int>()(sizeof...(Args), 3), int>
, 它仍然失败并出现相同的错误.
Per [comparisons.less]:
template 少结构{constexpr bool operator()(const T& x, const T& y) const;};
constexpr bool operator()(const T& x, const T& y) const;
返回: x .
运算符是 constexpr
.因此,就 less
而言,您的代码很好.
但是,从技术上讲,MSVC实际上就在这里—在 C++17 中,非类型模板参数不应具有类型 void*
.MSVC 实际上诊断了这一点.无论如何,这纯粹是巧合.
您可以直接使用 <
作为解决方法:
template <typename... Args,typename std::enable_if::type = 0>无效测试(std::tuple)
(注意用int
代替了void*
,这样语言学究绝对无话可说.)
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]:
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.)
这篇关于enable_if + std::less + sizeof... 的组合使 MSVC 失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!