Как предсказать что-то, имеющее числовой тип со знаком?

Предположим, у меня есть некоторый шаблонный код, который выполняет следующее:

T x = foo();
T y = -x;

Теперь, если T не числовой тип (или в котором не реализован унарный минус), компиляция просто не удастся. Но если это unsigned int, unsigned short и т. Д., Это будет успешно, с предупреждением. Так что я хотел бы иметь возможность сделать

T x = foo();
if (/* magic condition */ {
T y = -x;
}

Могу ли я написать в выражении условие — которое проверяется во время компиляции или во время выполнения — типа T является неким числовым типом со знаком? например используя typeid?

Замечания:

  • Утверждение тоже было бы неплохо, но я бы хотел что-то более гибкое.

4

Решение

C ++ 11 имеет is_unsigned черта, которую вы можете использовать в static_assert:

#include <type_traits>

template <typename T>
void foo()
{
static_assert(std::is_unsigned<T>::value);

T x = /* ... */
T y = -x;

/* ... */
}

Если вам нужно, чтобы проверка была более динамичной, просто вставьте ее в if состояние:

template <typename T>
void foo()
{
if (!std::is_unsigned<T>::value) {
/* To arrive here and for the following
not to error out, we must have a numeric
type that's not unsigned! */

T x = /* ... */
T y = -x;
}
else {
/* Do something else for unsigned numeric
types */
}
}

Более сложные решения связаны с перегрузками, std::enable_if и все виды других шаблонных мета-хакеров, но все, что вам нужно, может быть выше.

6

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

Да, ты можешь.

static_assert(std::is_unsigned<T>::value, "Not unsigned!");

(Вы должны включить type_traits, чтобы это работало.)

Затем вы можете корректировать процесс компиляции, даже если enable_if если ты уверен, что другого пути нет :).

4