如何实现自定义span类对右值数组的CTAD自动推导?
实现自定义span从右值连续序列自动推导模板参数
问题核心
std::span的默认推导指南不支持直接从右值std::array(或其他右值连续序列)构造并推导为std::span<const T, N>,但自定义span可以通过显式编写构造函数和推导指南实现这一需求。
解决方案代码
1. 自定义custom_span类
#include <array> #include <cstddef> #include <type_traits> template <typename T, std::size_t Extent = std::dynamic_extent> class custom_span { public: // 基础构造:指针+大小 constexpr custom_span(T* ptr, std::size_t size) noexcept : m_ptr(ptr), m_size(size) {} // 绑定右值std::array(const右值引用,避免修改临时对象) template <typename U, std::size_t N> constexpr custom_span(const std::array<U, N>&& arr) noexcept : m_ptr(arr.data()), m_size(N) {} // 绑定右值原生数组 template <typename U, std::size_t N> constexpr custom_span(const U (&&arr)[N]) noexcept : m_ptr(arr), m_size(N) {} // 核心成员函数实现 constexpr T* data() const noexcept { return m_ptr; } constexpr std::size_t size() const noexcept { return m_size; } constexpr T& operator[](std::size_t idx) const noexcept { return m_ptr[idx]; } private: T* m_ptr; std::size_t m_size; };
2. 编写推导指南
// 从右值std::array推导为custom_span<const U, N> template <typename U, std::size_t N> custom_span(const std::array<U, N>&&) -> custom_span<const U, N>; // 从右值原生数组推导为custom_span<const U, N> template <typename U, std::size_t N> custom_span(const U (&&)[N]) -> custom_span<const U, N>; // 可选:支持左值容器的推导(对齐std::span行为) template <typename Container> custom_span(Container&) -> custom_span<typename Container::value_type, std::dynamic_extent>; template <typename Container> custom_span(const Container&) -> custom_span<const typename Container::value_type, std::dynamic_extent>;
3. 测试验证
int main() { // 右值std::array推导为custom_span<const int, 3> auto x = custom_span(std::array{1, 2, 3}); static_assert(std::is_same_v<decltype(x), custom_span<const int, 3>>); // 右值原生数组推导为custom_span<const int, 4> auto y = custom_span({1, 2, 3, 4}); static_assert(std::is_same_v<decltype(y), custom_span<const int, 4>>); // 左值std::array推导为custom_span<int, 3> std::array arr{5,6,7}; auto z = custom_span(arr); static_assert(std::is_same_v<decltype(z), custom_span<int, 3>>); return 0; }
关键说明
- 构造函数使用
const右值引用接收临时对象,既保证可以绑定右值,又避免误修改临时对象,符合const T类型的span语义。 - 推导指南明确指定从右值序列推导出
const元素类型的span,解决了编译器无法自动推导的问题。 std::span默认不支持该场景是出于生命周期安全考量,但只要自定义span的生命周期不超过临时对象的生命周期,这种用法就是安全的。
内容的提问来源于stack exchange,提问作者Krupip
相关产品推荐
相关产品推荐

