C++ Visual C++ 2013 中的 11 std::enable_if 重载

C++ 11 std::enable_if overloading in Visual C++ 2013

本文关键字:C++ enable if 重载 std Visual 2013 中的      更新时间:2023-10-16

以下代码片段取自 folly,检查一个整数在编译时是否大于另一个整数。

#include <limits>
#include <type_traits>
template <typename RHS, RHS rhs, typename LHS>
bool greater_than_impl(
  typename std::enable_if<
    (rhs <= std::numeric_limits<LHS>::max()
      && rhs >= std::numeric_limits<LHS>::min()),
    LHS
  >::type const lhs
) {
  return lhs > rhs;
}
template <typename RHS, RHS rhs, typename LHS>
bool greater_than_impl(
  typename std::enable_if<
    (rhs > std::numeric_limits<LHS>::max()),
    LHS
  >::type const
) {
  return false;
}
template <typename RHS, RHS rhs, typename LHS>
bool greater_than_impl(
  typename std::enable_if<
    (rhs < std::numeric_limits<LHS>::min()),
    LHS
  >::type const
) {
  return true;
}
template <typename RHS, RHS rhs, typename LHS>
bool greater_than(LHS const lhs) {
  return greater_than_impl<
    RHS, rhs, typename std::remove_reference<LHS>::type
  >(lhs);
}
int test()
{
    auto v = greater_than<int, 0, int>(0);
    std::cout << v << std::endl;
    return 0;
}

GCC 4.8.2 向我显示了预期的编译结果,但 Visual C++ 2013 在第二个模板函数greater_than_impl给了我一个错误:

C2995:已定义函数模板

似乎无法识别std::enable_if重载,Visual C++ 2013 是否缺少任何 SFINAE 功能?

>VC++ 2013不支持constexpr。据我所知,他们将maxmin实现为非常量static函数。您不能在需要常量表达式的地方使用它们,即:

#include <limits>
#include <array>
int main()
{
    std::array<int, std::numeric_limits<int>::max()> a;
}
error C2975: '_Size' : invalid template argument for 'std::array', expected compile-time constant expression

作为一种解决方法,我尝试复制libstdc++的numeric_limits实现,如下所示:

struct wrapper_base
{
  // member variables
};
template <typename T>
struct wrapper : public wrapper_base
{
    static const T max()
    {
        return T();
    }
    static const T min()
    {
        return T();
    }
};
template <>
    struct wrapper<int>
{
    static const int max()
    {
        return INT_MAX;
    }
    static const int min()
    {
        return INT_MIN;
    }
};

不幸的是,这会产生相同的函数模板重定义错误。您可以直接使用 INT_MAXINT_MIN,但这需要专门针对 16 种类型(在 libstdc++ 的情况下)。最好完全避免这种方法并遵循Praetorian的建议。