CV合格的数据成员和转换

时间:2016-08-11 20:46:13

标签: c++ const

这个question引用了C ++标准来证明CV限定类型的对齐和大小必须与非CV限定等效类型相同。这似乎很明显,因为我们可以使用from sklearn.manifold import MDS fig, ax=plt.subplots(ncols=5, figsize=(12,3)) for rs in range(5): M = MDS(n_components=2, metric=True, random_state=rs, dissimilarity='precomputed') A = M.fit(Ar_dist).embedding_ ax[rs].scatter(A[:,0],A[:,1], c=[{0:"b", 1:"g", 2:"r"}[t] for t in Se_targets]) T隐式地将const T&类型的对象强制转换为static_cast

但是,假设我们有两种类型都具有相同的成员变量类型,除了一种具有所有reinterpret_cast成员变量而另一种不具有const成员变量。如:

typedef std::pair<T, T> mutable_pair;
typedef std::pair<const T, const T> const_pair;

此处,该标准不允许我们从const_pair&的实例生成mutable_pair。也就是说,我们不能说:

mutable_pair p;
const_pair& cp = reinterpret_cast<const_pair&>(p);

这会产生未定义的行为,因为它未在标准中列为reinterpret_cast的有效用法。然而,从概念上讲,似乎没有理由为什么不允许这样做。

所以...为什么要关心?你总是可以说:

const mutable_pair& cp = p;


嗯,如果您只希望一名成员获得const资格,可能会关心。如:

typedef std::pair<T, U> pair;
typedef std::pair<const T, U> const_first_pair;

pair p;
const_first_pair& cp = reinterpret_cast<const_first_pair&>(p);
显然,这仍然是未定义的行为。然而,由于CV限定类型必须具有相同的大小和对齐,因此没有概念上的原因,这应该是未定义的。

那么,标准是否有某些原因不允许它?或者仅仅是标准委员会没有想到这个用例的问题?

对于任何想知道这可能有什么用处的人:在我的特定情况下,我遇到了一个用例,能够将std::pair<T, U>转换为std::pair<const T, U>&非常有用。我正在实现一个专门的平衡树数据结构,它按键提供log(N)查找,但在每个节点内部存储多个元素。 find / insert / rebalance例程需要内部改组数据元素。 (数据结构称为T-tree。)由于数据元素的内部重排通过触发无数的复制构造函数而对性能产生负面影响,因此如果可能,实现内部数据混洗以利用移动构造函数是有益的。

不幸的是......我也希望能够提供符合AssociativeContainer的C ++标准要求的界面,这需要value_type std::pair<const Key, Data>。请注意const。这意味着无法移动单个对对象(或至少键不能移动)。他们要复制,因为密钥存储为const对象。

为了解决这个问题,我希望能够在内部将元素存储为可变对象,但是当用户通过迭代器访问它时,只需将键转换为const引用。不幸的是,我无法将std::pair<Key, Data>投射到std::pair<const Key, Data>&。而且我无法提供某种返回包装类或类似内容的解决方法,因为它不会满足AssociativeContainer的要求。

因此这个问题。

因此,考虑到CV合格类型的大小和对齐要求必须与非CV合格等效类型相同,是否有任何概念上的理由说明为什么不允许这样的演员?或者仅仅是标准作家没有想到的东西?

1 个答案:

答案 0 :(得分:4)

将类型作为模板参数并不意味着您不会有不同的对齐方式,可以更改类内容,例如,通过专门化或模板元编程。考虑:

template<typename T> struct X { int i; };
template<typename T> struct X<const T> { double i; };

template<typename T> struct Y {
    typename std::conditional<std::is_const<T>::value, int, double>::type x;
};