在不使用模板的情况下获取 std::array 引用
Getting an std::array reference without using templates
如果一个函数接收一个数组范围(开始/结束(作为指针,有没有办法再次将其视为std::array
?
void xyz(int* begin, int* end) {
// at this point i know that at this memory range there's
// an array<int> of end - begin size
// is there any way i can get that back?
}
int main() {
array<int, 5> x = {1, 2, 3, 4, 5};
xyz(x.begin(), x.end());
}
我知道我可以x
作为参数传递,但我必须指定它的大小。解决方法是使用模板,但我想知道有没有一种方法可以在不使用模板和不复制它的情况下重建对x
的类型化引用?
如果(开始/结束(不足以重建xyz
内部的类型xyz
有没有其他方法可以提供数组的内存表示形式,并让它重建类型......相信它在这个内存地址上?
std::array
被实现为一个struct
,将 C 样式的固定长度数组作为其唯一的数据成员。 迭代器begin()
通常是指向数组1的第一个元素的原始指针。
1:@bitmask评论中提出了一个很好的观点:"请注意,std::array<T,N>::iterator
不一定是原始指针。通常是,但不一定是。也不必转换为T*
。因此,由于编译器的实现细节,您的代码C++无效并进行编译。
数组的第一个元素的地址保证与数组本身的地址相同。并且结构的第一个成员的地址保证与结构本身的地址相同。 因此,从理论上讲,假设begin
迭代器实际上是指向第一个数组元素的原始指针,那么您应该能够将begin
类型转换为std::array*
指针 - 但前提是您在编译时知道用于实例化该std::array
的EXACT模板参数值,例如:
void xyz(int* begin, int* end) {
using array_type = array<int, 5>; // OK
array_type *arr = reinterpret_cast<array_type*>(begin);
...
}
int main() {
array<int, 5> x = {1, 2, 3, 4, 5};
xyz(x.begin(), x.end());
}
但是,如果你不能保证begin
只来自一个std::array
,并且是指向其第一个元素的原始指针,这将惨败。
虽然您可以从开始传入的迭代器类型中确定必要的T
模板参数,但不能仅使用迭代器来确定必要的N
模板参数。 该值必须是编译时常量,但获取 2 个迭代器之间的距离只能在运行时确定:
void xyz(int* begin, int* end) {
using array_type = array<int, ???>; // <-- can't use (end-begin) here!!!
array_type *arr = reinterpret_cast<array_type*>(begin);
...
}
或:
template<typename Iter>
void xyz(Iter begin, Iter end) {
using array_type = array<iterator_traits<Iter>::value_type, ???>; // <-- can't use (end-begin) here!!!
array_type *arr = reinterpret_cast<array_type*>(begin);
...
}
首先使用迭代器作为函数参数的全部意义在于抽象出容器类型,使其未知或不需要。 因此,从迭代器中收集的信息确定原始容器类型是非常困难的,如果不是不可能的话。
因此,在这种情况下,如果您确实需要访问std::array
那么最好只是传递整个std::array
本身,而不是它的迭代器:
template<typename T, size_t N>
void xyz(array<T, N> &arr) {
...
}
int main() {
array<int, 5> x = {1, 2, 3, 4, 5};
xyz(x);
}
- 如何获取std::result_of函数的返回类型
- 如何使用 lower_bound/upper_bound 从 std::set 获取索引号?
- 从返回 std::optional of std::vector 的函数中获取结果到调用方
- 如何在C++中获取 std::u8string 的正确长度?
- 从组件的 std::type_index 获取派生最多的类型
- std::cin 从控制台获取两种不同的变量类型,'storing'以后使用第二种类型?
- 为什么 std::set.erase(first, last) 会影响从中获取 (first, last) 的容器?
- ostream 运算符<< 为获取 STL 容器而过载,传递 std::string 会破坏它?
- 在 std::variant 中按类型获取索引
- 获取 std::函数以推断按引用传递/按值传递
- 如何获取 std::filesystem::p ath 中的最后一个目录?
- 如何获取两个 std::map 的公钥?
- 如何使用 std::invoke_result_t 获取函数的返回类型
- 在不使用模板的情况下获取 std::array 引用
- 我可以对 std::array 使用自定义分配器来获取安全加密密钥吗?
- 获取未知分段错误"(地址)在 std::__cxx11::basic_string<char, std::char_traits<char>,..., std::分配器<cha
- 通过 Ctypes 将 std:vector 从 C++ 传递到 Python:获取无意义的值
- 在瓦尔格林德的泄漏摘要中使用 std::ios::sync_with_stdio(fasle) 打印时获取"still reachable"
- 是否可以使用 std::文件系统获取根名称列表?
- 如何使 std::istream 从键盘获取输入(如 std::cin)?