返回其参数或检查 nullptr 的函数

Function returning its argument or checking for nullptr

我想循环一个向量并过滤掉所有非空指针元素。我正在寻找一个 std 函数来检查是否为 nullptr 或 std 函数实际上 returns 传递给它的任何东西(比如 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

没有。

我确实发现 identity 躺在身边有时很有用:

struct identity_t {
  template<class T>
  T operator()(T&& t)const{ return std::forward<T>(t); }
  constexpr identity_t() {}
};
constexpr identity_t identity;

(它将右值转换为副本,以延长参考生命周期)

主要是我在编写带有可选映射的函数时使用它,比如转换过滤器函数:identity 是转换的默认值,always_true 是过滤器的默认值。

标准库中没有这样的东西。从概念上讲,你想要的是:

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>{});

如果您不喜欢输入 {}s,您可以通过制作一个变量模板来缩短它。


就是说,这个问题:

[](const auto a) { return a; } ); // This is awkward

与其说它笨拙不如说它效率低下——那是两份副本(一份进一份出)。你想要:

[](const auto& a) { return static_cast<bool>(a); }

或者真的只是强制提前 bool 转换:

[](bool b){ return b; }

坚持使用 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,你可以在logical_not上使用not_fnnot1