Взгляните на is_detected
из основы TS v2 (также возможна реализация). Это дает вам хорошую базу на случай частых проверок различных операций. Это в основном позволяет вам проверить, возможна ли указанная операция с данными типами.
Сначала вы определяете тип вашей операции:
template <typename Lhs, typename Rhs>
using multiplication_t = decltype(std::declval<Lhs>() * std::declval<Rhs>());
затем вы делаете из него черту типа:
template <typename Lhs, typename Rhs>
constexpr bool can_multiply = is_detected<multiplication_t, Lhs, Rhs>::value;
Теперь вы можете использовать черту в качестве условия для enabled_if
:
template <typename T, typename = std::enable_if_t<can_multiply<T, unsigned int>>
T power (T base, unsigned int exponent) {
// ...
}
Это также добавляет читабельность (по крайней мере, imo), потому что can_multiply
четко выражает ваше намерение.
Здесь - полная реализация в качестве примера.
Еще один пример с большим количеством операций.