从可变替代方案中推导出 const 模板参数

问题描述 投票:0回答:1

当函数采用

std::span
const T
时,它无法从传入的可变跨度中推导出跨度类型。
然而,用户定义的类型是否可以允许从可变替代方案中推导 const 替代方案(也许通过推导指南的帮助)?

template<typename T>
struct MySpan
{};

template<typename T>
void takingConst(std::span<const T>)
{}
template<typename T>
void takingMyConst(MySpan<const T>)
{}

int square(int num) 
{
    std::span<int> stdSpan{};
    takingConst(std::span<const int>(stdSpan));

    MySpan<int> mySpan{};
    takingMyConst(mySpan); //Any way to make this work?
}
c++ templates type-deduction deduction-guide
1个回答
0
投票

使非

const
MySpan<T>
继承自
MySpan<const T>

这里有一个很容易理解的方法:

template<typename T>
struct MySpan : public MySpan<const T> {
    MySpan() = default;
    MySpan(T* ptr, std::size_t size) : MySpan<const T>(ptr, size) {}
    T* data() const { return const_cast<T*>(MySpan<const T>::data()); }
    T& operator[](std::size_t i) const { return data()[i]; }
    using MySpan<const T>::size;
};

template<typename T>
struct MySpan<const T> {
    MySpan() = default;
    MySpan(const T* ptr, std::size_t size) : ptr(ptr), sz(size) {}
    const T* data() const { return ptr; }
    const T& operator[](std::size_t i) const { return data()[i]; }
    std::size_t size() const { return sz; }
private:
    const T* ptr = nullptr;
    std::size_t sz = 0;
};

这里有一个不重复代码的方法:

template<typename T>
struct MySpan;

namespace detail {
    template<typename T>
    struct my_span_members {
    private:
        T* ptr = nullptr;
        std::size_t sz = 0;
        template<typename>
        friend struct ::MySpan;
    };
}

template<typename T>
struct MySpan : std::conditional_t<std::is_const_v<T>, detail::my_span_members<T>, MySpan<const T>> {
private:
    using base = std::conditional_t<std::is_const_v<T>, detail::my_span_members<T>, MySpan<const T>>;
public:
    MySpan() = default;
    MySpan(T* ptr, std::size_t size) : base{ static_cast<const T*>(ptr), size } {}
    template<std::size_t N>
    MySpan(std::type_identity_t<T>(& arr)[N]) : MySpan(arr, N) {}
    // ...
    T* data() const { return const_cast<T*>(base::ptr); }
    std::size_t size() const { return base::sz; }

    T& operator[](std::size_t i) const { return data()[i]; }
    // ...
};
© www.soinside.com 2019 - 2024. All rights reserved.