如何在使用模板时从std :: vector中删除元素?

时间:2016-03-31 15:00:11

标签: c++ templates vector

我有一个相当简单的模板类,我将项目存储在向量中。但是,当我尝试擦除元素时出现以下错误:

C2678: binary '==': no operator found which takes a left-hand operand of type
      'TestComponent' (or there is no acceptable conversion)

这是我正在使用的代码:

#pragma once
#include <vector>

template<class T>
class ComponentManager {
    ComponentManager() {};
    ~ComponentManager() {};

    T* newComponent() {
        components.emplace_back(T());
        return &components.back();
    }

    // This is the method I'm having trouble with
    void destroyComponent(T* t) {
        components.erase(std::remove(components.begin(), components.end(), *t), components.end());
    }

private:
    std::vector<T> components;
};

是的,我知道这会导致无效的指针和诸如此类的东西。没必要去那里。

3 个答案:

答案 0 :(得分:3)

如果您尝试通过指针擦除,则需要使用正确的算法。 enum MyError { Some(&'static str) } struct State; impl State { pub fn new() -> State { State } pub fn work(&self) -> Result<(), MyError> { Err(MyError::Some("hi")) } } 在元素之间进行相等比较。根据您的评论,您不希望这样做,因此您可能更愿意选择std::remove_if

std::remove

请注意,保持指向void destroyComponent(T* t) { components.erase( std::remove_if(components.begin(), components.end(), [t](const T& comp) { return &comp == t; }), components.end() ); } 的指针并不是特别安全,因为插入向量可能会导致重新分配,这会使所有先前保存的指针无效。您可能需要考虑使用其他容器(或者只有vector或更好的vector<T*>)。

答案 1 :(得分:2)

std::remove搜索由开始和结束迭代器定义的给定序列,用于给定值,指定为第三个参数。显然,值的类型必须实现相等比较运算符,以便std::remove将序列中的值与给定值进行比较。

您的TestComponent类未实现==运算符,如错误消息所示。

答案 2 :(得分:1)

首先,你的解决方案是危险的:看起来你保留了存储在std::vector内的对象的指针,除非你提前预留足够的空间,否则当你添加新元素时你会得到一个悬空指针。如果你保留足够的空间,你可能应该通过指针而不是值来删除对象:

components.erase(std::remove_if(components.begin(), components.end(), [t]( const T &tc ) { return &tc == t; } ), components.end());

除非您可以按值唯一地标识对象,然后您需要为该类实现正确的operator==

我建议将TestComponentstd::unique_ptr存储在一起,然后std::vector您就不会遇到内存重新分配问题,并且您的移除工作将按预期工作,而不会实现operator==

template<class T>
class ComponentManager {
    ComponentManager() {};
    ~ComponentManager() {};

     template< class... Args >
     T *newComponent( Args...&& args ) {
        components.emplace_back(std::make_unique<T>(std::forward<Args>(args)...));
        return components.back().get();
    }

    // This is the method I'm having trouble with
    void destroyComponent(T* t) {
        components.erase(std::remove(components.begin(), components.end(), t), components.end());
    }

private:
    std::vector<std::unique_ptr<T>>> components;
};