给定一个模板,其非类型参数决定非常量的大小 int
数组成员,如何在编译时通过整数索引访问数组元素?我希望通过类模板的 getter 方法进行访问 at
.
我想既然类模板必须在运行前实例化,我可以传递另一个非类型类模板的 enum
前一类的成员值 at
确保index
的方法参数是编译时常量。
我离开了类模板deliberate_error
undefined 查看其参数是否在编译时计算,并在错误消息中查看编译时结果。
template <unsigned int N>
struct compile_time_int {
enum {num = N};
};
template <unsigned int N>
struct array_wrapper {
int arr[N];
template <unsigned int Ind>
constexpr int const& at(compile_time_int<Ind> const& index) const {
return arr[index.num];
}
};
template <unsigned int> struct deliberate_error;
int main() {
compile_time_int<2> cti;
array_wrapper<3> aw;
aw.at(cti);
deliberate_error<cti.num> my_error1;
deliberate_error<aw.at(cti)> my_error2;
}
aw.at(cti);
没有给出错误,所以我想如果我将相同的表达式传递给 deliberate_error
实例 my_error2
, 编译器将显示 arr[2]
的值在错误消息中。
my_error1
导致 g++ error: aggregate 'deliberate_error<2u> my_error1' has incomplete type and cannot be defined
,
显示 cti
的包装整数值 2
.所以,我想如果我通过相同的 cti
反对aw
的getter,然后将结果传递给my_error2
, 我可以得到 arr[2]
在错误消息中。但相反,它打印:
error: the value of 'aw' is not usable in a constant expression
note: 'aw' was not declared 'constexpr'
note: in template argument for type 'unsigned int'
error: invalid type in declaration before ';'
所以,我尝试在 constexpr
之前加上至 aw
的声明,但这会产生更多不受欢迎的错误。这里有什么问题,我该如何解决?
最佳答案
(请注意,据我所知, std::array
和 std::get
已经解决了您的问题。)
主要问题是您需要您的实例 aw
成为constexpr
当然你需要用一些值来初始化它:
constexpr array_wrapper<3> aw = { 1, 2, 3 };
关于函数at
, 你可以把它写成一个普通函数,但只需将它指定为 constexpr
:
constexpr int const& at(int i) const {
return arr[i];
}
然后,aw.at(0)
可以用作常量表达式:Live Demo
这样做的好处是您可以在编译时和运行时表达式中使用此函数,分别使用静态和动态索引。
如果你真的想让它模板化,你可以把它写成一个非成员,比如 std::get<N>
或作为类成员,但使用 int
类型的模板参数(或 size_t
或类似)。这简化了它的定义(你可以去掉你的 compile_time_int
类模板):
template<int Index>
constexpr int const& at() const {
return arr[Index];
}
然后,aw.at<0>()
可以用作常量表达式:Live Demo
第二种方法的优点是索引保证是静态的,所以我们可以在函数中使用它进行静态边界检查,不会增加任何性能损失。我不知道第一个版本是否可行。
关于c++ - 编译时通过索引访问类模板的成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20724456/