How to implement a compile time getter, for a more concise call?

534 views Asked by At

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 enums 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.

0

There are 0 answers