I want to implement a compile-time getter in a way to make its call more concise. I have a non-type (unsigned int N
) class template foo
, which recursively inherits from foo<N - 1>
. Every foo
has its own enum
member called number
, which is initialized to the value of its corresponding N
. The base case is foo<0>
. For example, a foo<5>
object has 6 enum
s called number
, valued 0
through 5
. I want to implement a compile-time getter at
, but it's not as easy as prepending a constexpr
to the prototype:
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;
}
};
In g++ 4.8, I get several instances of the errors: error: 'index' is not a constant expression
, among other things. The rest just follow suit. Even if all client code calls at
with integer literals only, the getter won't compile. Why?
In any case, my solution was to implement a compile-time integer wrapper. It's simply a non-type (unsigned int N
) class template ctint
(short for compile-time int), whose enum
member mem
is initialized to its N
:
template <unsigned int N>
struct ctint {
enum {mem = N};
};
So, replacing foo<N>
and foo<0>
's getter methods, respectively, with:
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;
}
and
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;
}
works:
int main() {
foo<5> f;
static_assert( f.at( ctint<4>{} ) != 4 , "equals 4");
}
but makes the function call verbose. I’d like an implementation that’s library-free aside from parts (e.g. <iostream>
) that show something works but not help make it work. I’d like the getter to be able to optionally omit or have no <>
syntax or spelling out of a type name in the call, but not necessarily in the prototype or definition. I don't want it to involve array[]
s. If that’s impossible, I’d like to know the next-best way.