C ++:将容器转换为不同但兼容类型的容器 [英] C++: converting a container to a container of different yet compatible type

查看:133
本文介绍了C ++:将容器转换为不同但兼容类型的容器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于类型 T1 ,我经常会遇到一个容器 C (或任何类型的包装类,甚至智能指针) code>,并且想要将 C 转换为 C ,其中 T2 T1 兼容。

It often happens to me to have a a container C (or whatever kind of wrapper class, even smart pointers) for a type T1, and want to convert such C<T1> into C<T2>, where T2 is compatible to T1.

C ++不允许我直接转换整个容器,并强制一个 reinterpet_cast 会导致未定义的行为,所以我需要创建一个新的 C< T2> / code>容器,并以 C< T1> T2

C++ doesn't allow me to directly convert the whole container, and forcing a reinterpet_cast would result in undefined behavior, so I would need to create a new C<T2> container and repopulate it with C<T1> items casted as T2. This operation could be quite expensive, both in time and space.

此外,在很多情况下,我确定强制执行 reinterpret_cast T2 T1 const 时,c $ c> ,或 T1 T2 是指针。

Moreover for many cases I'm pretty sure that forcing a reinterpret_cast would work fine with the code compiled by any compiler ever existed, for example when T2 is T1 const, or when T1 and T2 are pointers.

C< T2> 中转换 C< T1> 是否有任何干净和高效的方法?
例如,创建和重新填充 C< T2> container_cast 运算符并且只有当它不是二进制兼容 C< T1>

Is there any clean and efficient way to convert a C<T1> in a C<T2>?
For example a container_cast operator(/function?) that creates and repopulates a C<T2> if and only if it wouldn't be binary compatible to C<T1>?

推荐答案

除了其他人处理的所有其他问题:

Besides all the other issues dealt by others:


  • 转换并不意味着相同的内存占用

  • 模板类(您的问题中的容器,但从编译器的角度来看,容器只是另一个模板)的潜在特殊化,即使类型本身是二进制兼容的

  • 同一模板的不同实例化的无关性(对于一般情况)

根本不是技术的方法中的基本问题。如果苹果是水果,那么水果容器都不是苹果容器(简单演示),苹果容器也不是水果容器。尝试在一个苹果盒子里装一个西瓜!

There is a basic problem in the approach that is not technical at all. Provided that an apple is a fruit, neither a container of fruits is a container of apples (trivially demonstrated) nor a container of apples is a container of fruit. Try to fit a watermelon in a box of apples!

进入更多的技术细节,特别处理继承,甚至不需要转换,(派生对象已经是基类的对象),如果允许将派生类型的容器转换为基本类型,则可以向容器添加无效元素:

Going to more technical details, and dealing specifically with inheritance where no conversion is even required, (a derived object is already an object of the base class), if you were allowed to cast a container of the derived type to the base type, then you could add invalid elements to the container:

class fruit {};
class apple : public fruit {};
class watermelon : public fruit {};
std::vector<apple*> apples = buy_box_of_apples();
std::vector<fruit*> & fruits = reinterpret_cast< std::vector<fruit*>& >(apples);
fruits.push_back( new watermelon() ); // ouch!!!

最后一行是完全正确的:你可以添加 watermelon 向量< fruit *> 。但净效果是您已向向量< apple *> 添加了西瓜你已经破坏了类型系统。

The last line is perfectly correct: you can add a watermelon to a vector<fruit*>. But the net effect is that you have added a watermelon to a vector<apple*>, and in doing so you have broken the type system.

不是一切看起来很简单的一切看起来事实上是理智的。这类似于你不能将 int ** 转换为 const int ** 的原因,即使第一个思想是应该允许的。事实是,允许这样会破坏语言(在这种情况下const正确性):

Not everything that looks simple in a first look is in fact sane. This is similar to the reason why you cannot convert an int ** to a const int ** even if the first thought is that it should be allowed. The fact is that allowing so would break the language (in this case const correctness):

const int a = 5;
int *p = 0;
int **p1 = &p;       // perfectly fine
const int **p2 = p1; // should this be allowed??
*p2 = &a;            // correct, p2 points to a pointer to a const int
**p1 = 100;          // a == 100!!!

这让我们回到你在其中一个评论中提供的例子给另一个答案一般来说,我将使用一个向量而不是一个集合,因为设置内容是不可变的):

Which brings us back to the example you provided in one of the comments to another answer (to prove the point in general, I'll use a vector and instead of a set since set contents are immutable):

std::vector<int*> v1;
std::vector<const int*> &v2 = v1; // should this be allowed?
const int a = 5;
v2.push_back( &a );  // fine, v2 is a vector of pointers to constant int
                     // rather not: it IS a vector of pointers to non-const ints!
*v1[0] = 10;         // ouch!!! a==10

这篇关于C ++:将容器转换为不同但兼容类型的容器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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