为什么编译器选择const方法而不是非const方法

Why compiler choose the const method instead of non-const?

本文关键字:方法 const 是非 编译器 为什么 选择      更新时间:2023-10-16

我试图实现一个三维张量使用uBlas矩阵从boost作为后端。其中一个功能是获取对切片的引用,并允许对矩阵进行简单的赋值。

下面是张量类的片段:
template<class L, class M>
class tensor {
public:
    typedef L layout_type;
    typedef std::size_t size_type;
    typedef M array_type;
private:
    size_type size1_;
    size_type size2_;
    size_type size3_;
    array_type data_;
public:
    /**
     * Return a constant reference to the internal storage of a dense tensor, i.e. the raw data
     * It's type depends on the type used by the tensor to store its data
     */
    BOOST_UBLAS_INLINE
    const array_type &data() const {
        return data_;
    }
    /**
     * Return a reference to the internal storage of a dense tensor, i.e. the raw data
     * It's type depends on the type used by the tensor to store its data
     */
    BOOST_UBLAS_INLINE
    array_type &data() {
        return data_;
    }
    /**@}*/
    /**
     * @name Slices' access
     * Accessors for slices across each dimension
     */
    /**@{*/
    BOOST_UBLAS_INLINE
    typename layout_type::template slice<1>::matrix_slice_type 
    at_dim1_slice(uint32_t i) {
        return ublas::trans(ublas::project(data(), layout_type::template slice<1>::coord1(i, size1_, size2_, size3_),
                layout_type::template slice<1>::coord2(i, size1_, size2_, size3_)));
    }
}

layout_type看起来像:

template<class M>
struct basic_dim2_major {
    typedef M matrix_type;
    template<int DIM, class DUMMY = void>
    struct slice {
    };
    template<class DUMMY> struct slice<1, DUMMY> {
        struct trans {
            template<class T>
            auto operator()(T &x) ->decltype(ublas::trans(x))
            {
                return ublas::trans(x);
            }
        };
        typedef ublas::matrix_slice<matrix_type> matrix_slice_type;
        typedef typename std::result_of<trans(matrix_slice_type&)>::type Type;
        static BOOST_UBLAS_INLINE
        Type
        orient(matrix_slice_type &data){
            return ublas::trans(data);
        }
        static BOOST_UBLAS_INLINE
        ublas::slice coord1(size_type i, size_type size_i, size_type size_j, size_type size_k) {
            return ublas::slice(i, size_i, size_k);
        }
        static BOOST_UBLAS_INLINE
        ublas::slice coord2(size_type i, size_type size_i, size_type size_j, size_type size_k) {
            return ublas::slice(0, 1, size_j);
        }
     }
} 

用例如下:

ublas::matrix slice1(3,4);
tensor<> t(2,3,4);
t.at_dim1_slice(0) = slice1;

问题存在于这一行:

    return ublas::trans(ublas::project(data(), layout_type::template slice<1>::coord1(i, size1_, size2_, size3_),
        layout_type::template slice<1>::coord2(i, size1_, size2_, size3_)));

当trans和project函数同时使用时,编译器会选择project和trans的const重载,因此不能像上面那样赋值。但是,如果我只留下项目,则使用非const方法,一切都可以正常工作。不幸的是,由于设计的存储布局(映射到二维矩阵),切片的转置是必要的。

const matrix_slice<const M> project (const M &data, const typename matrix_slice<M>::slice_type &s1, const typename matrix_slice<M>::slice_type &s2);
matrix_slice<M> project (matrix_slice<M> &data, const typename matrix_slice<M>::slice_type &s1, const typename matrix_slice<M>::slice_type &s2);

是否有任何解决方案来指示正确的函数重载?还是我哪里出错了?

当const和非const版本同时可用时,如果对象本身是const,则编译器选择const版本。如果对象是非const,则编译器选择非const版本。这就是函数的解析方式。

所以在你的代码中,如果选择了const版本,那么对象必须是const本身。

还要注意,在const成员函数中,this是一个const指针,从它返回的任何成员数据也是const