std::ranges::empty

来自cppreference.com
< cpp‎ | ranges
 
 
 
定义于头文件 <ranges>
inline namespace /*unspecified*/ {

    inline constexpr auto empty = /*unspecified*/;

}
(C++20 起)
(定制点对象)
调用签名
template< class T >

    requires /* see below */

constexpr bool empty(T&& t);

确定 t 是否拥有任何元素。

tT 类型对象。对 ranges::empty 的调用表达式等价于:

  1. bool(std::forward<T>(t).empty()) ,若该表达式合法。
  2. 否则为 (ranges::size(std::forward<T>(t)) == 0) ,若该表达式合法。
  3. 否则为 bool(ranges::begin(t) == ranges::end(t))

所有其他情况下,对 ranges::empty 的调用非良构,这能在 ranges::empty(t) 出现于模板实例化的立即语境中时导致替换失败

表达式等价

表达式 e 表达式等价于表达式 f ,若 ef 拥有相同效果,均为潜在抛出或均非潜在抛出(即 noexcept(e) == noexcept(f) ),且均为常量子表达式或均非常量子表达式。

定制点对象

名字 ranges::empty 代表一个定制点对象,它是字面 semiregular 类类型的 const 函数对象。为说明目的,以 __empty_fn 表示其类型的 cv 无限定版本。

__empty_fn 的所有实例均相等。在相同参数上调用类型 __empty_fn 的不同实例的效果是等价的,无关乎指代该实例的表达式是左值还是右值,以及是否为 const 限定(然而不要求 volatile 限定的实例可调用)。从而能自由地复制 ranges::empty 并且能彼此替代地使用其副本。

给定类型集合 Args... ,若 std::declval<Args>()... 满足上面对于 ranges::empty 的参数要求,则 __empty_fn 实现 std::invocable<__empty_fn, Args...>std::invocable<const __empty_fn, Args...>std::invocable<__empty_fn&, Args...>std::invocable<const __empty_fn&, Args...> 。否则, __empty_fn 的函数调用运算符不参与重载决议。

示例

#include <iostream>
#include <ranges>
#include <vector>
 
template <std::ranges::input_range R>
void print(R&& r)
{
    if (std::ranges::empty(r)) {
        std::cout << "\tEmpty\n";
        return;
    }
 
    std::cout << "\tElements:";
    for (const auto& element : r) {
        std::cout << ' ' << element;
    }
 
    std::cout << '\n';
}
 
int main()
{
    {
        auto v = std::vector<int>{1, 2, 3};
        std::cout << "1. calling ranges::empty on std::vector:\n";
        print(v);
 
        v.clear();
        print(v);
    }
    {
        std::cout << "2. calling ranges::empty on std::initializer_list:\n";
        auto il = {7, 8, 9};
        print(il);
 
        print(std::initializer_list<int>{});
    }
    {
        std::cout << "2. calling ranges::empty on a raw array:\n";
        int array[] = {4, 5, 6}; // 数组拥有已知边界
        print(array);
    }
    {
        struct NoEmptyNorSize : private std::vector<int> {
            auto begin() { return std::vector<int>::begin(); }
            auto end() { return std::vector<int>::end(); }
        };
 
        std::cout << "3. calling ranges::empty on an object that satisfies only case 3):\n";
        print(NoEmptyNorSize{});
    }
}

输出:

1. calling ranges::empty on std::vector:
	Elements: 1 2 3
	Empty
2. calling ranges::empty on std::initializer_list:
	Elements: 7 8 9
	Empty
2. calling ranges::empty on a raw array:
	Elements: 4 5 6
3. calling ranges::empty on an object that satisfies only case 3):
	Empty

参阅

(C++17)
检查容器是否为空
(函数模板)