Я хочу реализовать метод получения времени компиляции таким образом, чтобы сделать его вызов более лаконичным. У меня нетип типа (unsigned int N
) шаблон класса foo
, который рекурсивно наследует от foo<N - 1>
, каждый foo
имеет свой enum
член называется number
, который инициализируется значением соответствующего N
, Базовый случай foo<0>
, Например, foo<5>
Объект имеет 6 enum
называется number
ценится 0
через 5
, Я хочу реализовать компилятор времени компиляции at
, но это не так просто, как подготовить constexpr
к прототипу:
template <unsigned int N>
struct foo : protected foo<N - 1> {
protected:
enum {number = N};
public:
constexpr int const& at(const unsigned int index) {
static_assert(index <= N, "out of range");
return this->foo<index>::number;
}
};
template <>
struct foo<0> {
protected:
enum {number = 0};
public:
constexpr int const& at(const unsigned int index) {
static_assert(index == 0, "out of range");
return this->number;
}
};
В g ++ 4.8 я получаю несколько примеров ошибок: error: 'index' is not a constant expression
кроме всего прочего. Остальные просто следуют примеру. Даже если все вызовы кода клиента at
только с целочисленными литералами геттер не будет компилироваться. Зачем?
В любом случае, моим решением было реализовать целочисленную обертку во время компиляции. Это просто не тип (unsigned int N
) шаблон класса ctint
(сокращение от int во время компиляции), чьи enum
член mem
инициализируется к его N
:
template <unsigned int N>
struct ctint {
enum {mem = N};
};
Итак, замена foo<N>
а также foo<0>
Методы получения, соответственно, с:
template <unsigned int ind>
constexpr int const& at(ctint<ind> const& ctint_par) {
static_assert(ctint_par.mem <= N, "out of range");
return this->foo<ctint_par.mem>::number;
}
а также
template <unsigned int ind>
constexpr int const& at(ctint<ind> const& ctint_par) {
static_assert(ctint_par.mem == 0, "out of range");
return this->number;
}
работает:
int main() {
foo<5> f;
static_assert( f.at( ctint<4>{} ) != 4 , "equals 4");
}
но делает вызов функции многословным. Мне нужна реализация, которая не содержит библиотек, кроме отдельных частей (например, <iostream>
), которые показывают что-то работает, но не помогают заставить это работать. Я хотел бы, чтобы получатель мог опционально опускать или не иметь <>
синтаксис или написание имени типа в вызове, но не обязательно в прототипе или определении. Я не хочу вовлекать array[]
s. Если это невозможно, я бы хотел узнать следующий лучший способ.
Задача ещё не решена.
Других решений пока нет …