You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现自定义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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 04:36:20