通过克隆另一个容器的元素来创建智能指针的容器
Creating the container of smart pointers by cloning elements of another container
我有一个 class,它支持克隆(通过方法 clone
)。我在 std::unique_ptr
.
的向量中有一堆它的实例
现在,我想从上述向量创建一个 std::set
相同的智能指针,最好是在其构造期间。明显的设计如下:
#include <memory>
#include <set>
#include <vector>
class A
{
public:
/// type of itself
typedef A self;
A() = default;
A(const self& another) = default;
virtual ~A() = default;
std::unique_ptr<A> clone() const
{
return std::make_unique<A>();
}
};
class SetOfA
{
public:
SetOfA() = default;
// Here is the method I would like to improve
SetOfA(const std::vector<std::unique_ptr<A> >& data)
{
//do not like this loop, prefer this to be in initialization part?
for (const auto& d : data) {
set_of_a.insert(std::move(d->clone()));
}
}
private:
std::set<std::unique_ptr <A> > set_of_a;
};
但是有没有办法避免构造函数中的这个 for
循环并将 std::set
构造移到初始化部分?
如果可以使用 Boost,这里有一个可能的解决方案:
SetOfA(const std::vector<std::unique_ptr<A>>& data) :
set_of_a(
boost::make_transform_iterator(data.begin(), std::mem_fn(&A::clone)),
boost::make_transform_iterator(data.end(), std::mem_fn(&A::clone)))
{ }
您可以使用 std::transform
来避免 for
循环在 std::set
.
中插入值
SetOfA(const std::vector<std::unique_ptr<A> >&data)
{
std::transform(data.begin(), data.end(), std::inserter(set_of_a, set_of_a.begin()), [](auto& a){return a->clone();});
// or better
//std::transform(data.begin(), data.end(), std::inserter(set_of_a, set_of_a.begin()), std::mem_fn(&A::clone));
}
它使用 C++14 及更高版本编译。请在此处找到经过测试的版本 https://godbolt.org/z/jzvaKovn7.
为了将所有内容都放在初始化部分,您可以使用 lambda 或 Functor,将数据转换为集合,如下所示:
class SetOfA
{
struct VectorToSetConverter
{
std::set<std::unique_ptr<A>> operator() (const std::vector<std::unique_ptr<A> >&data) const
{
std::set<std::unique_ptr<A>> set_of_a;
std::transform(data.begin(), data.end(), std::inserter(set_of_a, set_of_a.begin()), std::mem_fn(&A::clone));
return set_of_a;
}
};
public:
SetOfA() = default;
SetOfA(const std::vector<std::unique_ptr<A> >&data)
: set_of_a(std::move(VectorToSetConverter()(data))) // move might not be necessary
{
}
private:
std::set<std::unique_ptr <A> > set_of_a;
};
我有一个 class,它支持克隆(通过方法 clone
)。我在 std::unique_ptr
.
现在,我想从上述向量创建一个 std::set
相同的智能指针,最好是在其构造期间。明显的设计如下:
#include <memory>
#include <set>
#include <vector>
class A
{
public:
/// type of itself
typedef A self;
A() = default;
A(const self& another) = default;
virtual ~A() = default;
std::unique_ptr<A> clone() const
{
return std::make_unique<A>();
}
};
class SetOfA
{
public:
SetOfA() = default;
// Here is the method I would like to improve
SetOfA(const std::vector<std::unique_ptr<A> >& data)
{
//do not like this loop, prefer this to be in initialization part?
for (const auto& d : data) {
set_of_a.insert(std::move(d->clone()));
}
}
private:
std::set<std::unique_ptr <A> > set_of_a;
};
但是有没有办法避免构造函数中的这个 for
循环并将 std::set
构造移到初始化部分?
如果可以使用 Boost,这里有一个可能的解决方案:
SetOfA(const std::vector<std::unique_ptr<A>>& data) :
set_of_a(
boost::make_transform_iterator(data.begin(), std::mem_fn(&A::clone)),
boost::make_transform_iterator(data.end(), std::mem_fn(&A::clone)))
{ }
您可以使用 std::transform
来避免 for
循环在 std::set
.
SetOfA(const std::vector<std::unique_ptr<A> >&data)
{
std::transform(data.begin(), data.end(), std::inserter(set_of_a, set_of_a.begin()), [](auto& a){return a->clone();});
// or better
//std::transform(data.begin(), data.end(), std::inserter(set_of_a, set_of_a.begin()), std::mem_fn(&A::clone));
}
它使用 C++14 及更高版本编译。请在此处找到经过测试的版本 https://godbolt.org/z/jzvaKovn7.
为了将所有内容都放在初始化部分,您可以使用 lambda 或 Functor,将数据转换为集合,如下所示:
class SetOfA
{
struct VectorToSetConverter
{
std::set<std::unique_ptr<A>> operator() (const std::vector<std::unique_ptr<A> >&data) const
{
std::set<std::unique_ptr<A>> set_of_a;
std::transform(data.begin(), data.end(), std::inserter(set_of_a, set_of_a.begin()), std::mem_fn(&A::clone));
return set_of_a;
}
};
public:
SetOfA() = default;
SetOfA(const std::vector<std::unique_ptr<A> >&data)
: set_of_a(std::move(VectorToSetConverter()(data))) // move might not be necessary
{
}
private:
std::set<std::unique_ptr <A> > set_of_a;
};