具有相同参数类型但具有不同常量限定符的std :: vector的cast [英] Cast of std::vector of same parameter type but with different constant qualifier

查看:143
本文介绍了具有相同参数类型但具有不同常量限定符的std :: vector的cast的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

the question is pretty simple, is it in general safe a static cast (or some other cast) from

to 

二进制,我不明白为什么原生类型会有所不同, code> const 是一个不会影响元素大小的语言约束,所以我认为

std::vector< const Foo >

/ p>

binary-wise, i don't see why the native types would differ, after all, the const is a language constraint that should not affect the size of the element, or so i think

can i do 

不担心这会吸收某人的船?

std::vector< const Foo >& someFunc() { std::vector< Foo >& ref = ... return *reinterpret_cast<std::vector< const Foo >*>(& ref); }


推荐答案

忽略你说std :: vector的那一刻,假装你有一些其他良好定义的向量实现。你的代码在技术上是不安全的,因为 T T const 是完全不同的,因为C ++语言允许向量< T> 向量< T const> 以非常不同的方式进行专门化。考虑下面的代码:

Ignoring that you said std::vector for the moment and pretending you had some other less well defined vector implementation. Your code would be technically unsafe not because T and T const are quite different but because the C++ language permits vector<T> and vector<T const> to be specialised in ways that are quite different. Consider the following code:

#include <iostream>

template <class T>
struct vector {
    T* start_;
    T* end_;
    T* cap_end_;
};

template <class T>
struct vector<T const> {
    bool gotcha_;
    T* start_;
    T* end_;
    T* cap_end_;
};

struct foo { };

int
main()
{
    std::cout
        << sizeof(vector<foo>) << '\n'
        << sizeof(vector<foo const>) << '\n'
        ;
}

请注意,还有其他更多的恶意更改可能会使你的生活悲惨。例如下面的成员被重新排序:

Note that there are other more pernicious changes that could make your life miserable. Such as the following where the members are reordered:

#include <iostream>

template <class T>
struct vector {
    T* start_;
    T* end_;
    T* cap_end_;
};

template <class T>
struct vector<T const> {
    T* end_;
    T* cap_end_;
    T* start_;
};

template <class T>
long size(vector<T> const& v)
{
    return v.end_ - v.start_;
}

struct foo { };

int
main()
{
    vector<foo> v;
    v.start_ = new foo[10];
    v.end_ = v.start_ + 1;
    v.cap_end_ = v.start_ + 10;


    std::cout
        << size(v) << '\n'
        << size(*reinterpret_cast<vector<foo const>*>(&v)) << '\n'
        ;

    return 0;
}

写到std :: vector,的标准库规范来知道这样的专门化是否符合。

Wrt to std::vector, I am not familiar enough with the fine details of the standard library specification to know whether such specialisations would be conformant or not. Perhaps someone more well versed in the standard can comment.

请注意我在回答将模板类转换为更一般的专业化可能有助于解释此问题。

Note some of what I said in answer to Casting templated class to more general specialization may help explain this problem.

为了解决你的问题检测专业化有有办法使你的代码不安全,通过使用没有专门化的类,但重载的非成员函数,我不知道你会如何检测到。例如如下:

To address your question about detecting specialisations there are ways to make your code unsafe by using no specialisations of the class but overloaded non-member functions and I am o not sure how you would detect that. Such as in the following:

#include <iostream>

template <class T>
struct vector {
    T* start_;
    T* end_;
    T* cap_end_;
};


template <class T>
void init(vector<T>& v, size_t sz, size_t cap)
{
    v.start_ = new T[cap];
    v.end_ = v.start_ + sz;
    v.cap_end_ = v.start_ + cap;
}

template <class T>
void init(vector<T const>& v, size_t sz, size_t cap)
{
    v.end_ = new T const[cap];
    v.cap_end_ = v.end_ + sz;
    v.start_ = v.end_ + cap;
}

template <class T>
long size(vector<T>& v)
{
    return v.end_ - v.start_;
}

template <class T>
long size(vector<T const>& v)
{
    return v.cap_end_ - v.end_;
}

struct foo { };

int
main()
{
    vector<foo const> v;
    init(v, 1, 10);

    std::cout
        << size(v) << '\n'
        << size(*reinterpret_cast<vector<foo>*>(&v)) << '\n'
        ;
}

足够的坏消息。好消息是,如果你想使用一个通用接口获取一个现有的对象,并限制或调整可以做的对象,有一些简单,安全和可理解的方式做到这一点。查看std :: stack http://www.sgi.com/tech/stl /stack.html ,或者选择此答案 http://stackoverflow.com/a/994925/453436 什么是C ++中的代理类

Enough with the bad news. The good news is that if you want to take an existing object with a general interface and restrict or adjust what can be done with that object there is are some simple, safe and comprehensible ways of doing that. Take a look at std::stack http://www.sgi.com/tech/stl/stack.html or alternatively this answer http://stackoverflow.com/a/994925/453436 to What is Proxy Class in C++

这篇关于具有相同参数类型但具有不同常量限定符的std :: vector的cast的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆