The function returns its argument or checks for nullptr

I would like to loop over a vector and filter out all elements with a non-null pointer. I'm looking for a function std

that checks that something is a nullptr function or std

that actually returns whatever is passed to it (for example std::forward

), since a null pointer will evaluate to a value 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


source to share


3 answers


Pinned file in std

, you can use std::remove_copy_if

with 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

      

Or you can use remove_copy

transfer nullptr

:



std::remove_copy(dynamicObjects.begin(), dynamicObjects.end(),
    std::back_inserter(existingObjects), 
    nullptr);

      

If you really like copy_if

, you can use not_fn

or not1

instead logical_not

.

+5


source


Nope.

I find what identity

lies around to be useful sometimes:

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

      



(it converts rvalues ​​to copies, for a reference lifespan extension)

I mainly use it when writing functions with optional mappings, such as the filter function of filters: identity

is the default for the transformation, and always_true

is the default filter.

+2


source


There is nothing like this in the standard library. Conceptually what you need:

std::copy_if(dynamicObjects.begin(), dynamicObjects.end(),
    std::back_inserter(existingObjects), 
    bool);

      

assuming you can use type names as factory functions that construct instances of that type. But this is not something you can do in C ++. At least directly. We can write that:

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

      

If you don't like typing {}

s, you can shorten that by making a variable template.


However, the problem with this:

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

      

- it's not so much that it is inconvenient, how inefficient it is - that there are two copies (one in one, one). You need:

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

      

Or actually just force the conversion bool

before:

[](bool b){ return b; }

      

+1


source







All Articles