Могу ли я использовать 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>
, например.
Сразу рекомендую использовать 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};
}
Других решений пока нет …