Я не думаю, что возможно получить то, что вы хотите с помощью одной функции.
Даже если у вас есть функция constexpr
, я не думаю, что вы сможете определить, когда выполняется время выполнения и когда выполняется время компиляции, и действовать по-другому.
Но вы можете разработать различные функции.
К примеру, шаблон get<>()
, где аргумент шаблона является индексом, который может быть использован только с индексом известного во время компиляции и что может выполнить static_assert()
, и at(std::size_t)
, который может принимать индекс, вычисленный по время выполнения с проверкой времени выполнения.
Мимоходом:
1) Я полагаю, как обычно в STL, использование at()
для связанного проверяется доступ и operator[]()
для связанного неконтролируемого доступа
2), и я предложить использование индекс без знака или вы должны проверить, что индекс равен >= 0
.
Ниже приведен рабочий пример
#include <iostream>
#include <stdexcept>
template <class T, std::size_t Dim>
class Foo
{
private:
T _data[Dim];
public:
T const & operator[] (std::size_t idx) const
{ return _data[idx]; }
template <std::size_t IDX>
T const & get() const
{
static_assert(IDX < Dim, "out of range");
return this->operator[](IDX);
}
T const & at (std::size_t idx) const
{
if (idx >= Dim)
throw std::range_error("out of range");
return this->operator[](idx);
}
};
int main()
{
Foo<float, 2U> foo;
foo.get<0U>();
foo.get<1U>();
//foo.get<2U>(); // compiler error
for (auto i = 0U ; i < 5U ; ++i)
foo.at(i); // run time exception when i > 1
return 0;
}
спасибо, обновленный вопрос. – sharvey
Вы можете посмотреть на __builtin_constant_p для GCC, но вряд ли вы получите идеальное решение, потому что есть некоторые действительно странные поведения с GCC, когда вы пытаетесь сделать то, что вы предлагаете. –
Ваш 'foo [2]' доступ не выполняется в контексте 'constexpr', и ваш оператор также не является' constexpr'. Вы не получите ошибку времени компиляции. Чтобы достичь своей цели, используйте 'assert' (который будет выдавать ошибку' 'nonstockpr'', если false) вместо' static_assert'. –