本文介绍了enable_if + std::less + sizeof... 的组合使 MSVC 失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个非常简单的代码:

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 失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-01 22:13