在我的代码中,有时我需要从另一个容器构造一个容器。但是这些容器对象的类型不同,所以我不能使用复制构造函数。我的工作看起来像这样(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;
答案 0 :(得分: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);
答案 1 :(得分:0)
在c ++ 14中有一个提议,如果我没有错,将能够将另一个容器作为“可遍历”直接传递给容器的构造函数。
可以找到该提案的最新版本here。
答案 2 :(得分:0)
我认为问题是,让容器从任何可迭代的东西中实例化会导致很多意想不到的行为和歧义。例如:
auto mystring = std::string { "ABC" };
auto mylist = std::list { mystring };
应在此处将 mylist
实例化为只有一个元素的字符串列表(如当前 C++17 的情况),或作为三个字符 'A'、'B' 和'C',就像在可迭代展开中的情况一样?使展开显式可以巧妙地解决这个问题,即使写起来有点乏味。