首页 > 解决方案 > enable_if + std::less + sizeof... 的组合使 MSVC 失败

问题描述

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

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)。

它无法在具有 C++ 17设置的Visual Studio 2019 中编译。

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它会突然起作用。

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

标签: c++visual-c++

解决方案


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

运营商是constexpr。因此,就您而言,您的代码很好less

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

您可以<直接使用作为解决方法:

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

(请注意,int用 代替void*,因此语言学究绝对无话可说。)


推荐阅读