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.
CodePudding user response:
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:
- returns
c.empty()
So, std::empty(v)
and v.empty()
have the same effect in this case.
CodePudding user response:
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).
CodePudding user response:
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 });
}