【问题标题】:combination of enable_if + std::less + sizeof... makes MSVC failenable_if + std::less + sizeof... 的组合使 MSVC 失败
【发布时间】:2019-07-04 04:30:15
【问题描述】:

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

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));
}

这只是一个带有enable_if 条件的简单函数模板。 (用于进一步的 SFINAE)。

但在 Visual Studio 2019 with C++ 17 设置中编译失败

error C2672:  'test': no matching overloaded function found
error C2783:  'void test(std::tuple<_Types...>)': could not deduce template argument for '__formal'

但是我发现 它在 GCC 和 Clang 中编译得很好。为什么那个看似无辜的代码会失败?

有趣的是,如果我将 sizeof...(Args) 替换为 2,那么它会突然起作用。

编辑:我最初的问题没有在enable_if 中提供类型,但我发现void* 在C++ 17 中不允许作为非类型模板参数。但是没关系。因为即使我更改为std::enable_if&lt;std::less&lt;int&gt;()(sizeof...(Args), 3), int&gt;它仍然会失败并出现同样的错误。

【问题讨论】:

  • 为什么不直接sizeof...(Args) &lt; 3呢? ;-)
  • 请注意,void* 非类型模板参数在 C++17 中是不允许的。见stackoverflow.com/q/56003162
  • @L.F.哇,我不知道。但我认为 MSVC 仍然是错误的(或至少不一致),因为如果我将 sizeof 更改为 2,它就可以工作。
  • 是的,这不过是两个错误导致的巧合正确。
  • It does work 如果将模板更改为匿名类型而不是非类型,很有趣。

标签: c++ visual-c++


【解决方案1】:

[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;

返回: x &lt; y.

运营商是constexpr。因此,就less 而言,您的代码没有问题。

但是,从技术上讲,MSVC 实际上就在这里——非类型模板参数在 C++17 中不应具有类型 void*。 MSVC 实际上对此进行了诊断。无论如何,这纯属巧合。

您可以直接使用&lt; 作为解决方法:

template <typename... Args,
  typename std::enable_if<(sizeof...(Args) < 3), int>::type = 0>
void test(std::tuple<Args...>)

(注意int是用void*代替的,所以语言学究绝对无话可说。)

【讨论】:

  • 谢谢。我已经知道如何解决这个问题,但我的问题是“是什么让这个简单的代码在 MSVC 中失败??”
  • @i.stav MSVC 有时会神秘地失败 ;-)
  • 好吧,如果我将int 提供给enable_if 但仍然保留std::less,它仍然会失败。所以MSVC是完全错误的
猜你喜欢
  • 2016-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-27
  • 2023-03-23
  • 2014-08-29
  • 2012-10-26
  • 1970-01-01
相关资源
最近更新 更多