我有一个引用对象的函数,并使用用户定义的函数对其进行复制。我想将对象的副本构造函数作为此函数的默认值。可能吗?
template<class T>
void foo(T const & obj, std::function<T(T const &)> const & copy){
std::vector<T> iv;
size_t n=5;
for(size_t i=0U; i!=n; ++i){
iv.emplace_back(copy(obj));
}
//do stuff with iv
return;
}
答案 0 :(得分:2)
您无法获得对复制构造函数(或与此有关的任何构造函数)的引用,但可以将调用c'tor的对象创建包装在lambda中:
template<class T>
void foo(T const & obj, std::function<T(T const &)> const & copy = [](T const& t){ return T(t); }){
std::vector<T> iv;
size_t n=5;
for(size_t i=0U; i!=n; ++i){
iv.emplace_back(copy(obj));
}
//do stuff with iv
return;
}
然而,返回值优化将使其表现得好像您可以获取对副本c'tor的引用并对其进行调用,而一路没有太多副本。
您还可以通过另一层间接操作来摆脱另一个副本。由于emplace_back
通过引用接受一个参数,因此返回的值copy
必须及早实现,并在emplace_back
的实现中再次复制。如果要传递另一个对象(可转换为T
的对象),则可以保留另一个副本。我可以做到如下
template<class T>
void foo(T const & obj, std::function<T(T const &)> const & copy = [](T const& t){ return T(t); }){
struct {
T const& obj;
std::function<T(T const &)> const & copy;
operator T() {
return copy(obj);
}
} obtainer{obj, copy};
std::vector<T> iv;
size_t n=5;
for(size_t i=0U; i!=n; ++i){
iv.emplace_back(obtainer);
}
//do stuff with iv
return;
}
对obtainer
对象的引用被传递到emplace_back
的内部,当需要创建新对象时,转换函数将启动。我们可以期望RVO消除所有副本现在,并在副本c'tor的帮助下构造新值。