c++ - 如何在不获取未定义行为的情况下重新解释或转换具有已知内存布局的对象

标签 c++ casting c++17 undefined-behavior reinterpret-cast

我有一个带有 transposedView() 的矩阵类我多年来一直使用的方法作为行 vector 和列 vector 之间的“零开销”转换。

template<int M, int N=M, typename T = double>
struct mat {
    std::array<T,M*N> buf;
    // ...
    template<int Md = M, int Nd = N, typename = std::enable_if_t<Md == 1 || Nd == 1>>
    const mat<N, M, T>& transposedView() const {
        static_assert(M == 1 || N == 1, "transposedView() supports only vectors, not general matrices.");
        return *reinterpret_cast<const mat<N, M, T>*>(this);
    }
}

我曾经相信这一点,因为 mat<1,N> 的内存布局完全对应于 mat<N,1> ,但我have just learned该函数具有未定义的行为。您对我可以用什么替换此功能的内容/实现有什么建议吗?

最佳答案

你可以设计一个新的 View 类模板,比如std::string_view对应于std::string,或Eigen::Map对应于Eigen::Matrix(可见,这是C++中常见的设计)。 View 类模板可以简单地保存一个指向它查看的序列开头的指针和一个大小(如果你只想支持整个矩阵的 View ,你可以省略 size 成员,因为它可以从它的模板参数中推断出来).您的 transposedView 函数可以返回这样的 View 类。

template<int M, int N=M, typename T = double>
struct mat_view {
    T *begin;
    std::size_t size;
    // member functions you want to support
    // ...
}

template<int M, int N=M, typename T = double>
struct mat {
    std::array<T,M*N> buf;
    // ...
    template<int Md = M, int Nd = N, typename = std::enable_if_t<Md == 1 || Nd == 1>>
    const mat_view<N, M, T> transposedView() const {
        static_assert(M == 1 || N == 1, "transposedView() supports only vectors, not general matrices.");
        return {std::begin(buf), M * N};
    }
}

关于c++ - 如何在不获取未定义行为的情况下重新解释或转换具有已知内存布局的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68569078/

相关文章:

c++ - 内联变量的多次销毁

c++ - SIGABRT C++,抛出异常

c++ - 使 auto_cast 安全

c++ - 使用模板化函数参数的隐式类型转换

python - 在 PySpark 中将多列转换为字符串的有效方法

javascript - 在 Javascript 中将 BigInteger 转换为 Int64

c++ - 不复制就返回std::function

c++ - 我应该怎么做才能让 WS_MAXIMIZE 工作?

c++ - 如何有效使用Boost的intrusive_ptr?

c++ - 反汇编器 GLOBAL 关键字