В качестве простого примера рассмотрим следующий класс:
template <int N>
class A {
private:
std::array<double, N> m_vs = {};
public:
int size() {return N;}
void set_value(double d, int n=0) {m_vs[n] = d;}
double get_value(int n=0) {return m_vs[n];}
}
Допустим, у нас есть a = A<10>().
Я бы хотел, чтобы компилятор выдавал ошибку, если я набираю a.set_value(1, 20), поскольку известно, что это будет за пределами допустимого, но не выдавал никаких ошибок, если я напишу a.set_value(1, i), поскольку i может быть допустимым.
Возможно ли добиться такого поведения?
@user12002570 user12002570 компилятор может знать, что 20 выходит за пределы, но понятия не имеет, допустимо i или нет. Поэтому я хочу иметь ошибку в первом случае, но не во втором.
Нет никакой разницы между переданными аргументами 20 и i здесь, когда вы вызывали функцию (lvalue/rvalue и т. д. здесь не учитываются). Они одинаковы в контексте призвания. По сути, оба привязаны к параметру функции, а параметр функции n не является constexpr.
Вы можете сделать параметр нетипового шаблона, который равен constexpr.





Вы не получите проверку времени компиляции вашего значения времени выполнения. Вы можете получить
constexprПример:
template <std::size_t N>
class A {
private:
std::array<double, N> m_vs = {};
public:
constexpr std::size_t size() const { return N; }
// use these with runtime `n`s:
double get_value(std::size_t n) {
if (n >= N) throw std::out_of_range("get_value: n >= N");
return m_vs[n];
}
void set_value(double d, std::size_t n) {
if (n >= N) throw std::out_of_range("set_value: n >= N");
m_vs[n] = d;
}
// use these with `n`s known at compile time:
template <std::size_t n = 0>
double get_value() {
static_assert(n < N, "n < N failed");
return m_vs[n];
}
template <std::size_t n = 0>
void set_value(double d) {
static_assert(n < N, "n < N failed");
m_vs[n] = d;
}
};
Использование:
int main() {
A<10> a;
a.set_value(3.141); // n == 0, all's well (if N > 0, else compile time error)
a.set_value<10>(3.141); // compile time time error, 10 is out-of-bounds
a.set_value(3.141, 10); // runtime access out-of-bounds, throws exception
}
В конце концов, это было относительно просто. Спасибо! :)
std::integral_constant и udl могут быть альтернативным синтаксисом: a.set_value(3.141, 10_c).
@Jarod42 Да, конечно!
«поскольку
iможет быть действительным...» Так как же компилятор мог принять такое решение во время выполнения? Параметр функции неconstexpr.