我想以一种使其调用更简洁的方式实现编译时 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。如果那是不可能的,我想知道下一个最好的方法。