Перегрузка C++ 11 std::enable_if в Visual C++ 2013

Следующий фрагмент кода был взят из 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?


person ichenq    schedule 25.02.2014    source источник
comment
Было бы очень полезно включить дополнительную информацию об ошибках в ваш вопрос. На каких строках появляется ошибка? Какой точный текст ошибки он вам дает?   -  person Captain Obvlious    schedule 25.02.2014
comment
Единственный связанный отчет об ошибке, который я смог найти: Странное поведение std::enable_if‹T› приводит к ошибке C2995 в Visual C++.   -  person    schedule 25.02.2014
comment
Для этого требуется constexpr для numeric_limits::max() и min(), которых нет в VS2013. Это может сработать, если вы установите последнюю версию CTP, я считаю, что это добавляет некоторую поддержку constexpr, но даже в этом случае маловероятно, что они обновили stdlib. Но я не понимаю необходимости в этом в любом случае; если у вас есть поддержка constexpr, почему бы просто не реализовать ее, как здесь? Кроме того, C++14 добавляет constexpr к std::greater::operator().   -  person Praetorian    schedule 25.02.2014


Ответы (1)


VC++ 2013 не поддерживает constexpr. И из того, что я могу сказать, они реализуют max и min как неконстантные 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

В качестве обходного пути я попытался скопировать реализацию numeric_limits в libstdc++, что-то вроде следующего:

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_MAX и INT_MIN напрямую, но это потребует специализации для 16 типов (в случае libstdС++). Вероятно, лучше вообще избегать этого подхода и следовать совет Преторианца.

person Community    schedule 25.02.2014