шаблоны переменных и std :: enable_if

Могу ли я использовать enable_if (или есть какой-то альтернативный метод) с переменными шаблона. например

typedef float Float;
typedef double Double;

template<class T>
constexpr Bool IsFloat = std::is_same_v<T, Float>;

template<class T>
constexpr Bool IsDouble = std::is_same_v<T, Double>;

template<class T>
constexpr Bool IsFloatingPoint = IsFloat<T> || IsDouble<T>;

template<class T>
using EnableIfFloatingPoint = std::enable_if_t<IsFloatingPoint<T>>;

template
<
class T,
typename = EnableIfFloatingPoint<T>
>
constexpr T Pi = T(3.1415926535897932384626433832795);

Visual Studio выдает мне ошибку компилятора, говорящую «слишком мало аргументов шаблона», когда я пытаюсь использовать Pi<float>, например.

2

Решение

Сразу рекомендую использовать std::is_floating_point вместо того, чтобы вручную крутить собственный механизм обнаружения с плавающей точкой. Кроме того, вы сможете использовать _v суффикс вместо ::value по состоянию на C ++ 17.

Как было упомянуто в некоторых комментариях, использование самого SFINAE для шаблонов переменных не имеет особого смысла, но вы могли бы достичь своего решения, позволяя только типам с плавающей запятой иметь возможность принимать значение Pi пытаясь установить переменную шаблон типа std::enable_if_t< std::is_floating_point<T>::value, T>, который, конечно, будет иметь только выведенный тип, если условие выполнено.

template<class T>
using EnableIfFloatingPoint = std::enable_if_t<std::is_floating_point<T>::value, T>;

template<class T>
constexpr T Pi = EnableIfFloatingPoint<T>(3.1415926535897932384626433832795);

Pi<T> для целочисленных типов T просто не скомпилируется, потому что
EnableIfFloatingPoint<T> не будет выводить какой-либо тип, но я не буду рассматривать этот SFINAE.

Лучшим решением было бы иметь constexpr шаблон функции с соответствующим static_assert сообщение, подтверждающее, что шаблон был создан с «правильным» типом.

template<class T>
constexpr T Pi()
{
using is_fp = std::is_floating_point<T>;
static_assert( is_fp::value, "Pi must be instantiated with floating point types.");
return T{3.1415926535897932384626433832795};
}
3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]