Как часть некоторых функций Geometri c, которые я реализую для проекта, я подумал, что было бы неплохо помочь ограничить типы, которые могут быть переданы в библиотеку, только Geometri c Types. Итак, я написал следующую структуру, чтобы помочь с этим:
template<typename T>
struct Geometric {
static_assert(std::is_arithmetic_v<T>, "T Must be Arithmetic!");
static_assert(std::is_same_v<T, std::decay_t<T>>, "Must be raw type!");
};
//...
template<typename T>
struct point2 : Geometic<T> {
//...
};
Затем, потому что моей библиотеке нужно использовать пользовательский тип, который подчиняется всем общим соглашениям арифметических типов c (по крайней мере, насколько это возможно). что касается этого проекта) я решил, что простое решение для интеграции этого типа в библиотеку состоит в том, чтобы просто добавить запись для std::is_arithmetic
для этого типа:
using rational_t = boost::multiprecision::cpp_rational;
template<>
struct std::is_arithmetic<rational_t> : std::true_type {};
using rational_point = point2<rational_t>;
Однако этот код последовательно выдает "T должно быть арифметика c! " сообщение об ошибке во время компиляции. Поэтому я немного покопался в реализации Microsoft этих черт типа и обнаружил нечто, чего я не ожидал: вывод std::is_arithmetic_v<T>
происходит непосредственно от других констант, , а не из связанной с ним структуры.
//MSVC2019 Code found in 'xtr1common', line# 197
// STRUCT TEMPLATE is_arithmetic
template <class _Ty>
_INLINE_VAR constexpr bool is_arithmetic_v = // determine whether _Ty is an arithmetic type
is_integral_v<_Ty> || is_floating_point_v<_Ty>;
template <class _Ty>
struct is_arithmetic : bool_constant<is_arithmetic_v<_Ty>> {};
Это, конечно, блокировало мой код, потому что моя специализация is_arithmetic<rational_t>
не имела абсолютно никакого влияния на определение is_arithmetic_v<rational_t>
.
Это определенно блокировало меня, потому что я ожидал специализация работать в обратном порядке, получая is_arithmetic_v
из is_arithmetic
, как это подробно описано на странице CPPReference для этого типа черты :
Шаблон вспомогательной переменной
template< class T >
inline constexpr bool is_arithmetic_v = is_arithmetic<T>::value;
Возможная реализация
template< class T >
struct is_arithmetic : std::integral_constant<bool,
std::is_integral<T>::value ||
std::is_floating_point<T>::value> {};
Как и определение MST C этой черты (и многих других черт, которые, кажется, следовать аналогичным закономерностям) законным в соответствии со стандартом, или это ошибка при внедрении? Если мне нужно специализировать эти виды констант в будущем, каков идеоматический c способ сделать это?