enable_if + std :: less + sizeof ...的组合会使MSVC失败

时间:2019-07-04 04:30:15

标签: c++ visual-c++

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

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,那么它突然起作用了。

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

1 个答案:

答案 0 :(得分:3)

[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实际上就在这里-非类型模板参数在C ++ 17中不得具有类型void*。 MSVC实际上诊断出了这一点。无论如何,那纯粹是巧合。

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

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

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