4

在我的代码中,有时我需要从另一个容器构造一个容器。但是这些容器对象是不同类型的,所以我不能使用复制构造函数。我所做的看起来像这样(C++11,我使用统一初始化和构造函数委托):

std::vector<int> source {1, 3, 5, 7, 9};
std::list<int> destination (source.begin (), source.end ());

我意识到 std::list 可以有一个这样的构造函数,让事情变得更漂亮:

template </* ... */>
class list
{
public:
    template <class Container> list (const Container& container)
    : list (container.begin (), container.end ())
    {
    }

    /* ... */
};

不幸的是,我只能为我自己的课程这样做,而不是为 STL 课程。所以第一个问题,STL 和 Boost 中不存在这样的构造函数是有原因的吗?第二个问题,是否有一种安全的方法来为 STL 容器实现这样的 ctor,也许通过以某种方式定义转换运算符?

这个问题当然只是一个方便的问题,对代码或程序行为无关紧要。但它可以使代码看起来更具可读性:

std::vector<int> source {1, 3, 5, 7, 9};
std::list<int> destination = source;
4

3 回答 3

7

您应该怀疑将一种容器类型的完整范围复制到另一种容器类型的代码。这是一项不常见的活动。

在 C++ 中,通常首选显式转换。通常不鼓励从一种类型转换为另一种类型的隐式转换和赋值运算符,因为它们有时会导致意外转换。

如果您确实需要在容器类型之间频繁转换,请尝试为转换定义显式帮助函数:

template<typename ToType, typename FromType>
ToType container_cast(const FromType& source)
{
    return ToType(source.begin(), source.end(), source.get_allocator());
}

然后你的例子变成:

std::vector<int> source {1, 3, 5, 7, 9};
auto destination = container_cast<std::list<int> >(source);
于 2013-09-15T15:56:47.727 回答
0

c++14 中有一个提议,如果我没记错的话,可以将另一个容器作为“可遍历”直接传递给容器的构造函数。

可以在此处找到该提案的最新版本。

于 2013-09-16T07:06:20.690 回答
0

我认为问题在于,让容器从任何可迭代的东西中实例化会导致很多意想不到的行为和歧义。例如:

auto mystring = std::string { "ABC" };
auto mylist = std::list { mystring };

mylist在此处实例化为仅包含一个元素的字符串列表(如当前 C++17 的情况),或作为三个字符“A”、“B”和“C”的列表,如可迭代展开中的情况?使展开显式巧妙地解决了这个问题,即使编写起来有点乏味。

于 2021-07-28T17:16:30.280 回答