具有继承的模板参数推断

时间:2018-12-12 15:52:40

标签: c++ templates

考虑这个小程序:

#include <memory>
#include <vector>

class Holder {
    std::vector<std::unique_ptr<A> > _items;

public:
    void push(A *v) {
        //Perform some checks and other stuff before pushing
        _items.emplace_back(v);
    };
    void push(std::unique_ptr<A> &v) {
        push(v.release());
    };
};

class A {

};

class B : public A {

};

int main()
{
    Holder h;
    std::unique_ptr<A> a;
    std::unique_ptr<B> b;

    // It works but it's too verbose
    h.push(a.release());
    h.push(b.release());

    // It works for a because it has the right type but not for b
    h.push(a);
    h.push(b);
}

我想知道是否有一种简单的方法来编写h.push(b)行而没有给自己所有权的开销。

我不想使用*b,因为指针必须在push方法中失去其所有权,并且我希望push方法尽可能易于使用。 / p>

我觉得我应该从push类中删除unique_ptr的{​​{1}}重载,并使用第一个有效的示例。

有什么主意吗?

3 个答案:

答案 0 :(得分:4)

这是正确的签名:

void push(std::unique_ptr<A> v) {
    //Perform some checks and other stuff before pushing
    push(std::move(v));
}

获取unique_ptr表示您正在获取所有权。

在呼叫站点:

// It works but it's too verbose
h.push(std::move(a));
h.push(std::move(b));

这既是必需的,也是因为您希望清除所有权变更代码。

请注意,std::move(b)代码将导致未定义的行为,因为A缺少虚拟析构函数。

// It works for a because it has the right type but not for b
h.push(a);

此代码有毒,并且会导致错误。您只是默默地更改了unique_ptr的所有权。 auto_ptr具有此属性,被发现几乎不可能正确使用,已被弃用,然后从标准中删除。

不要编写使unique_ptrauto_ptr一样的代码。

答案 1 :(得分:2)

您应该移动而不是通过引用传递对象:

for image_name in image_names:
    for datum in data:
        datum_name = datum.get("name", None)
        if datum_name == image_name:
           images_ids.append(datum.get("id", None))

然后:

void push(std::unique_ptr<A> v) {
    push(v.release());
};

但是唯一指针上的任何h.push(std::move(a)); h.push(std::move(b)); 都是难闻的气味,因此请以另一种方式实现推送:

release

并添加虚拟析构函数。

答案 2 :(得分:2)

对于export default class Posizionecliente extends Component { constructor(props) { super(props); this.contiService = new ContiService(); this.state = { conti: [], }; } componentDidMount() { this.contiService.getConti().then(r => this.setState({ conti: r.data.conti })); } } ,您应该始终拥有所有权,在这种情况下,您不必担心释放和创建新指针。而是使用std::unique_ptr函数。您可以将推送功能更改为此:

std::move

然后您将使用以下命令推入指针

void push (std::unique_ptr<A> v) { _items.push_back(std::move(v)); }