对象的构造函数作为函数参数

时间:2019-07-19 18:43:25

标签: c++ constructor binding

我有一个引用对象的函数,并使用用户定义的函数对其进行复制。我想将对象的副本构造函数作为此函数的默认值。可能吗?

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;
}

1 个答案:

答案 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的帮助下构造新值。