我有对象的向量和要过滤的标准向量。受this post的Moo-Juice的启发,我写了一个代码:
#include <algorithm>
#include <string>
#include <memory>
#include <vector>
struct Token {
char code;
int val;
Token(char c,int a) : code(c),val(a) {}
};
class FilterBase {
public:
virtual bool operator()(const std::shared_ptr<Token> p) =0;
};
class ByCode : public FilterBase {
public:
ByCode( char c) : code_(c) {}
virtual bool operator()(const std::shared_ptr<Token> p) {
return code_ == p->code;
}
private:
unsigned char code_;
};
int main() {
std::vector<std::shared_ptr<FilterBase>> filters;
filters.push_back(std::make_shared<ByCode>('A'));
filters.push_back(std::make_shared<ByCode>('B'));
std::shared_ptr<Token> p = std::make_shared<Token>('M', 20);
std::vector<std::shared_ptr<Token>> tokens;
tokens.push_back(p);
filters[0]->operator ()(p);
for (const std::shared_ptr<FilterBase> fi : filters) {
tokens.erase(std::remove_if(tokens.begin(), tokens.end(), *fi), tokens.end());
}
}
但不幸的是它没有编译,因为参数类型&#39; FilterBase&#39;是一个抽象类。嗯,我知道它是,我只是通过虚拟关键字使它工作...
答案 0 :(得分:1)
替换:
tokens.erase(std::remove_if(tokens.begin(), tokens.end(), *fi), tokens.end());
使用:
tokens.erase(std::remove_if(tokens.begin(), tokens.end(), std::ref(*fi)), tokens.end());
remove_if
使用其仿函数by-value,这会将*fi
切成基类的实例,该实例具有纯virtual
个对象。情况很糟糕。
std::ref
有一个重载的operator()
,如果MSVC没有搞砸了(例如,如果它调用运算符),它应该调用virtual operator()
*fi
错误的方式)。
如果失败,您可以编写自己的适配器:
template<typename T>
struct callable_by_ref {
T* t;
template<typename... Args>
auto operator(Args&&...args) const ->
decltype( std::declval<T&>()(std::declval<Args&&>()...) )
{
return (*t)(std::forward<Args>(args)...);
}
};
template<typename T>
callable_by_ref< typename std::remove_reference<T>::type >
call_by_ref( T&& t ) {
return {&t};
}
即使std::ref
没有,也应解决您的问题。
tokens.erase(std::remove_if(tokens.begin(), tokens.end(), call_by_ref(*fi)), tokens.end());
我在做什么:
callable_by_ref
基本上是一个快速完美的转发器,它上面有一个半功能的std::reference_wrapper
实现。 call_by_ref
为您创建此类对象的类型扣除。