C++20 span

C++20 span

概念

std::span<T, Extent> 类模板就是一块连续内存的视图(类似于 std::string_view ),简化原本C风格的基制指针+长度的使用方式。

模板形参:

  • T :元素类型;必须是完整对象类型且非抽象类
  • Extent :连续序列中的元素数,默认为动态长度(std::dynamic_extent

注意

  • span 能拥有静态 长度,此时序列中的元素数在编译期已知并在类型中编码,也可以拥有动态 长度。

  • 对于 span s,当有操作使得范围 [s.data(), s.data() + s.size()) 中的指针失效时,到 s 的元素的指针、迭代器和引用也会失效。这种情况对应于使用 span 来观察如 vector 这样的容器时。

实现一个简易的span

#include <iostream>
#include <array>
#include <vector>
#include <type_traits>

template<typename T>
class Span
{
public:
    constexpr Span(T* arr, size_t n) : m_data(arr), m_size(n) {} // 单纯的指针

    template<size_t N>
    constexpr Span(T (&arr)[N]) : m_data(arr), m_size(N) {} // 原生数组

    template<size_t N>
    constexpr Span(std::array<T, N>& arr) : m_data(arr.data()), m_size(N) {} // 数组容器
	// 其他具有老式连续迭代器的容器
    constexpr Span(std::vector<T>& arr) : m_data(arr.data()), m_size(arr.size()) {
        static_assert(!std::is_same<T, bool>::value, "std::vector<bool> does't have contiguous iterator!");
    }
    
    constexpr T* data() const { return m_data; }
    constexpr size_t size() const { return m_size; }

	constexpr T& operator[](size_t i) const { return *(m_data + i); }
	constexpr T& front() const { return m_data[0]; }
	constexpr T& back() const { return m_data[m_size - 1]; }

    constexpr Span<T> subSpan(size_t offset) const {
        return Span<T>(m_data + offset, m_size - offset);
    }
    constexpr Span<T> first(size_t n) const {
        return subSpan(0, n);
    }
    constexpr Span<T> last(size_t n) const {
        return subSpan(m_size - n);
    }
    
private:
    T* m_data;
    size_t m_size;
};

template<typename T>
inline constexpr Span<T> make_span(T* arr, size_t n) {
    return Span<T>(arr, n);
}
void zero(Span<char> sp){
    std::fill(sp.data(), sp.data() + sp.size(), 0);
}


int main()
{
    char aa[11] = "abcdefghij";
    std::array<char, 11> bb = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'};
    std::vector<char> cc = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'};
    size_t n = 11;
    char* pc = new char[n];
    
    zero(bb);
    zero(cc);
	zero(make_span(pc, n));
    zero({pc, n});

	std::cout << aa << std::endl << bb.data()<< std::endl;

	Span<char> sp(aa);
	auto ssp = sp.subSpan(4);

	std::cout << aa << std::endl << ssp.data()<< std::endl;

	zero(ssp); 

	std::cout << aa << std::endl << ssp.data()<< std::endl;

    delete[] pc;
}
posted @ 2024-09-16 19:27  3的4次方  阅读(16)  评论(0编辑  收藏  举报