简体   繁体   中英

Difference between std::vector::empty and std::empty

To check if a vector v is empty, I can use std::empty(v) or v.empty() . I looked at the signatures on cppreference, but am lacking the knowledge to make sense of them. How do they relate to each other? Does one implementation call the other?

I know that one comes from the containers library and the other from the iterators library, but that is about it.

Difference between std::vector::empty and std::empty

The difference between Container::empty member function and std::empty free function (template) is the same as difference between Container::size , std::size , Container::data , std::data , Container::begin , std::begin and Container::end , std::end .

In all of these cases for any standard container, the free function (such as std::empty ) simply calls the corresponding member function. The purpose for the existence of the free function is to provide a uniform interface between containers (and also std::initializer_list ) and arrays. Arrays cannot have member functions like the class templates can have, so they have specialised overload for these free functions.

If you are writing code with a templated container type, then you should be using the free function in order to be able to support array as the templated type. If the type isn't templated, then there is no difference between the choice of using member function or the free function other than the convenience of potential refactoring into a template (or just plain array).

There are three overloads of std::empty , but the one used by std::empty(v) for a vector v is the first:

template <class C>
constexpr auto empty(const C& c) -> decltype(c.empty()); // (since c++17, until c++20)

template <class C>
[[nodiscard]] constexpr auto empty(const C& c) -> decltype(c.empty());
(since C++20) // (since c++20)

This overload has the following effect:

  1. returns c.empty()

So, std::empty(v) and v.empty() have the same effect in this case.

std::empty returns the result of calling std::vector::empty .

std::empty is useful for scenarios where a container may or may not provide a member function empty() for types providing a member function empty , std::empty provides a default implementation, but for a custom type not providing this function you can provide a function empty at namespace scope for use in templates; thanks to argument dependent lookup the function in the same namespace as the parameter will be used as fallback:

namespace Custom
{
    struct Container
    {
        bool m_empty;
    };

    constexpr bool empty(Container const& c) // custom implementation for our own type
    {
         return c.m_empty;
    }
}

template<class T>
void PrintEmpty(char const* containerName, T&& container)
{
    using namespace std;
    std::cout << containerName << " is " << (empty(container) ? "empty" : "not empty") << '\n';
}

int main()
{
    PrintEmpty("std::vector<int>()", std::vector<int>());
    PrintEmpty("Container{}", Custom::Container{});
    PrintEmpty("Container{ true }", Custom::Container{ true });
}

To language-lawyer a bit, the C++20 standard says that a container a has its a.empty() member function return true if and only if a.begin() == a.end() ([container.requirements.general]).

The std::empty() non-member function is specified in [iterator.range]. The overload constexpr auto empty(const C& c)Returns: c.empty() .”

So, in the Standard, the non-member function is specified in terms of the member functions, not vice versa. In general, that doesn't mean that the implementation needs to have the non-member function actually call the member function, so long as it “behaves as if.” In this case, the relationship must hold for any allowed specialization of the STL container classes, or for custom container classes, so that constrains what the writers of the library are allowed to do.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM