我想循环一个向量并过滤掉所有非空指针元素。我正在寻找一个std
函数来检查nullptr或std
函数实际返回传递给它的函数(如std::forward
),因为空指针会评估为false
。
std::copy_if(dynamicObjects.begin(), dynamicObjects.end(),
std::back_inserter(existingObjects),
std::is_pointer<ObjectType*>); // This does not compile
std::copy_if(dynamicObjects.begin(), dynamicObjects.end(),
std::back_inserter(existingObjects),
std::forward<ObjectType*>); // This does not compile either
std::copy_if(dynamicObjects.begin(), dynamicObjects.end(),
std::back_inserter(existingObjects),
static_cast<bool>); // This won't help me :)
std::copy_if(dynamicObjects.begin(), dynamicObjects.end(),
std::back_inserter(existingObjects),
[] (const auto a) { return a; } ); // This is awkward
答案 0 :(得分:5)
坚持std
中的内容,您可以将std::remove_copy_if
与std::logical_not
一起使用。
std::remove_copy_if(dynamicObjects.begin(), dynamicObjects.end(),
std::back_inserter(existingObjects),
std::logical_not<ObjectType*>()); // or std::logical_not<> in C++14
或者,您可以使用remove_copy
传递nullptr
:
std::remove_copy(dynamicObjects.begin(), dynamicObjects.end(),
std::back_inserter(existingObjects),
nullptr);
如果您真的喜欢copy_if
,则可以使用not_fn
上的not1
或logical_not
代替。
答案 1 :(得分:2)
不。
我确实发现有identity
有时会有用:
struct identity_t {
template<class T>
T operator()(T&& t)const{ return std::forward<T>(t); }
constexpr identity_t() {}
};
constexpr identity_t identity;
(它将rvalues转换为副本,用于参考生命周期扩展)
主要是在编写具有可选映射的函数时使用它,例如变换滤镜函数:identity
是变换的默认值,always_true
是滤镜的默认值。
答案 2 :(得分:1)
在标准库中没有这样的东西。从概念上讲,你想要的是:
std::copy_if(dynamicObjects.begin(), dynamicObjects.end(),
std::back_inserter(existingObjects),
bool);
假设您可以使用类型名称作为构造该类型实例的工厂函数。但是,这不是你可以用C ++做的事情。至少直接。我们可以写下:
template <class T>
struct factory {
template <class... Args>
T operator()(Args&&... args) const {
return T(std::forward<Args>(args)...);
}
};
std::copy_if(dynamicObjects.begin(), dynamicObjects.end(),
std::back_inserter(existingObjects),
factory<bool>{});
如果您不想输入{}
,可以通过制作变量模板来缩短此项。
那说,这个问题:
[](const auto a) { return a; } ); // This is awkward
并不是那么尴尬,因为它效率低下 - 这是两个副本(一进一出)。你想要:
[](const auto& a) { return static_cast<bool>(a); }
或者只是提前强制bool
转换:
[](bool b){ return b; }