0

我想以一种使其调用更简洁的方式实现编译时 getter。我有一个非类型 ( unsigned int N) 类模板foo,它递归地继承自foo<N - 1>. 每一个foo都有自己的enum成员number,它被初始化为其对应的值N。基本情况是foo<0>。例如,一个foo<5>对象有 6 个enum称为number,值0通过5。我想实现一个编译时 getter at,但这并不像constexpr在原型前面添加 a 那样简单:

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仅使用整数文字调用,getter 也不会编译。为什么?

无论如何,我的解决方案是实现一个编译时整数包装器。它只是一个非类型 ( unsigned int N) 类模板ctint(compile-time int 的缩写),其enum成员mem被初始化为其N

template <unsigned int N>
struct ctint {
    enum {mem = N};
};

因此,将foo<N>foo<0>的 getter 方法分别替换为:

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>显示某些工作但无助于使其工作的部分(例如)。我希望 getter 能够<>在调用中选择性地省略或没有语法或拼写类型名称,但不一定在原型或定义中。我不希望它涉及array[]s。如果那是不可能的,我想知道下一个最好的方法。

4

0 回答 0