c++ - стандарт - cppreference if constexpr
static_assert, если выражения constexpr (2)
Я хочу создать шаблон класса
template <class T>
class X {
// here I'll use T::value (among other things)
};
T::value
часто является статической переменной constexpr, но не всегда. T::value
должно быть положительным, поэтому я хочу, чтобы люди знали это во время компиляции, когда это возможно.
Если T::value
всегда было constexpr, я бы добавил static_assert
как
static_assert(T::value > 0, "need positive number");
Можно ли добавить этот static_assert только в случаях, когда T::value
constexpr?
Мы можем написать is_valid
шаблона is_valid
(придумать лучшее имя) с двумя перегрузками:
template <typename T, int N = T::value>
constexpr bool is_valid(int) {
return N > 0;
}
template <typename T>
constexpr bool is_valid(...) {
return true;
}
Первая перегрузка будет действительна только в том случае, если T::value
является постоянным выражением, иначе это будет SFINAEd. Вторая перегрузка действительна, несмотря ни на что, поэтому мы устраняем перегрузку с параметром фиктивного int
.
Теперь мы тестируем его так:
static_assert(is_valid<T>(0), "need positive number");
Это работает для меня на clang ++:
#include <type_traits>
// The default case, returns true if the value is not constant.
template <typename T, typename = void>
struct IsNonConstantOrPositive {
static const bool value = true;
};
// The `constexpr` case. We check if we can evaluate `T::value == 0` which can only
// be evaluated at compile-time if `T::value` is constant. The whole `enable_if` thing
// is to provide a substitution to ensure SFINAE.
template <typename T>
struct IsNonConstantOrPositive<T, typename std::enable_if<T::value==0||true>::type> {
static const bool value = T::value > 0;
};
template <typename T>
struct X {
static_assert(IsNonConstantOrPositive<T>::value, "T::value should be positive");
};
Пример:
struct A { // const > 0, should succeed
static const int value = 123;
};
struct B { // const <= 0, should fail
static const int value = -1234;
};
struct C { // non-const, should succeed
static int value;
};
int main() {
X<A> a; // ok
//X<B> b; // error
X<C> c; // ok
}