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

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

本文介绍了如何在没有未定义行为的情况下重新解释或转换具有已知内存布局的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有 transposedView() 方法的矩阵类,我多年来一直使用它作为零开销";行向量和列向量之间的转换.

I have a matrix class with a transposedView() method that I have been using for years as a "zero overhead" conversion between row and column vectors.

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 的内存布局与 mat 完全对应,但我刚刚了解到这个函数有未定义的行为.你对我可以用什么来替换这个函数的内容/实现有什么建议吗?

I used to trust this because the memory layout of mat<1,N> corresponds exactly to mat<N,1>, but I have just learned that this function has Undefined Behavior. Do you have any advice on what I could replace the contents/implementation of this function with?

推荐答案

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

You can design a new view class template, like std::string_view corresponding to std::string, or Eigen::Map corresponding to Eigen::Matrix (so you can see, this is a common design in C++). The view class template may simply hold a pointer pointing to the beginning of the sequence it views and a size (if you only want to support a view for a whole matrix, you can omit the size member as it can be inferred from its template parameters). Your transposedView function can return such a view class instead.

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};
    }
}

这篇关于如何在没有未定义行为的情况下重新解释或转换具有已知内存布局的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-03 07:38