函数返回其参数或检查nullptr

时间:2017-05-23 19:19:32

标签: c++ c++11 c++14 c++17

我想循环一个向量并过滤掉所有非空指针元素。我正在寻找一个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

3 个答案:

答案 0 :(得分:5)

坚持std中的内容,您可以将std::remove_copy_ifstd::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上的not1logical_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; }