Boost C++ 库

...世界上最受推崇和专业设计的 C++ 库项目之一。 Herb SutterAndrei Alexandrescu, C++ 编码标准

概述

Boost.Compat 是 C++11 标准组件在后续 C++ 标准中的实现的仓库。它的目标受众是支持较低 C++ 标准但希望使用后续标准中添加的组件的 Boost 库作者。

Boost.Compat 的纳入标准如下

  • 实现应相对简单且仅包含头文件。

  • 组件必须完全实现标准功能,没有偏差或扩展。这允许(但不要求)在标准组件可用时,实现可以是一个简单的 using 声明。

  • 组件不得依赖任何 Boost 库,但 Boost.Config、Boost.Assert 或 Boost.ThrowException 除外。

  • 组件不得是词汇表类型,在库 API 中可见。用户永远不应看到 boost::compat 类型;Compat 类型的使用应仅限于库实现。

修订历史

1.87.0 版本的更改

  • 添加了 to_array.hpp(由 Ruben Perez Hidalgo 贡献)。

1.86.0 版本的更改

  • 添加了 bind_front.hppbind_back.hppinvoke.hppmem_fn.hppinteger_sequence.hpptype_traits.hpp

  • 添加了 function_ref.hpp

1.83.0 版本的更改

  • 添加了 latch.hppstd::latch 的实现(由 Christian Mazakas 贡献)。

  • 添加了 shared_lock.hppstd::shared_lock 的(部分)实现(由 Christian Mazakas 贡献)。

<boost/compat/bind_back.hpp>

描述

头文件 <boost/compat/bind_back.hpp> 实现了 C++20 函数 std::bind_back

bind_backstd::bind 的一个有限变体。它仅支持将函数对象的最后几个参数绑定到特定的参数值。

示例

struct X
{
    void f(int a, int b) const noexcept;
};

int main()
{
    auto fn = boost::compat::bind_back(&X::f, 1, 2);

    X x;
    fn(x); // calls x.f(1, 2)
}

概要

namespace boost
{
namespace compat
{

template<class F, class... A> auto bind_back(F&& f, A&&... a);

} // namespace compat
} // namespace boost

bind_back

template<class F, class... A> auto bind_back( F&& f, A&&... a );
返回值

函数对象 fn,使得 fn(b…​) 等价于 invoke(f, b…​, a…​)

<boost/compat/bind_front.hpp>

描述

头文件 <boost/compat/bind_front.hpp> 实现了 C++20 函数 std::bind_front

bind_frontstd::bind 的一个有限变体。它仅支持将函数对象的前几个参数绑定到特定的参数值。

示例

struct X
{
    void f(int a, int b) const noexcept;
};

int main()
{
    X x;
    auto fn = boost::compat::bind_front(&X::f, &x);

    fn(1, 2); // calls x.f(1, 2)
}

概要

namespace boost
{
namespace compat
{

template<class F, class... A> auto bind_front(F&& f, A&&... a);

} // namespace compat
} // namespace boost

bind_front

template<class F, class... A> auto bind_front(F&& f, A&&... a);
返回值

函数对象 fn,使得 fn(b…​) 等价于 invoke(f, a…​, b…​)

<boost/compat/function_ref.hpp>

描述

头文件 <boost/compat/function_ref.hpp> 实现了 C++26 类 std::function_ref

function_ref 是一个轻量级的多态函数包装器,它仅存储指向提供的 可调用 对象的指针和指向未指定函数的指针,这意味着它不参与可调用对象的所有权,也不分配内存。function_ref 的所有特化都满足 TriviallyCopyable

function_ref 支持 constnoexcept 的每种组合,并且对于编写高阶函数非常有用,因为它可以避免模板参数或分配(如 std::function 所知的那样)。

示例

int add(int x, int y) noexcept { return x * 10 + y; }

auto add2 = [](int x, int y) { return x * 100 + y; };

std::vector<boost::compat::function_ref<int(int, int)>> fns;
fns.push_back({add});
fns.push_back({add2});

for (auto fn : fns) {
  std::cout << fn(1, 2) << std::endl;
}

概要

namespace boost
{
namespace compat
{

template <class... S>
struct function_ref;

// cv is either `const` or empty
// noex is either `true` or `false`
template<class R, class... ArgTypes>
class function_ref<R(ArgTypes...) cv noexcept(noex)> {
public:
  template<class F> function_ref(F*) noexcept;
  template<class F> function_ref(F&&) noexcept;
  template<auto f> function_ref(nontype_t<f>) noexcept;
  template<auto f, class U> function_ref(nontype_t<f>, U&&) noexcept;
  template<auto f, class T> function_ref(nontype_t<f>, cv T*) noexcept;

  function_ref(const function_ref&) noexcept = default;
  function_ref& operator=(const function_ref&) noexcept = default;
  template<class T> function_ref& operator=(T) = delete;

  R operator()(ArgTypes...) const noexcept(noex);
};

} // namespace compat
} // namespace boost

构造函数

函数指针构造函数

template<class F> function_ref(F* fn) noexcept;
先决条件

fn != nullptr

效果

构造一个 function_ref,它使用提供的函数指针作为其可调用对象。

调用 function_ref 在表达式上等价于 invoke_r<R>(f, call-args…​)

对象构造函数

template<class F> function_ref(F&& fn) noexcept;
效果

构造一个 function_ref,它存储提供的可调用对象 fn 的地址。当 fn 不是指向成员的指针或指向成员函数的指针时,此重载才参与解析。

调用 function_ref 在表达式上等价于:+ invoke_r<R>(static_cast<cv T&>(f), call-args…​)

成员函数指针构造函数

template<auto f> function_ref(nontype_t<f>) noexcept;
效果

使用提供的指向成员函数的指针构造 function_ref。当 f 是指向成员的指针或指向成员函数的指针时,此重载才参与解析。

调用 function_ref 在表达式上等价于: invoke_r<R>(f, class-args)

示例
struct point { int x = 1, y = 2; };

point p;
compat::function_ref<int(point const&)> f(compat::nontype_t<&point::x>{});

BOOST_TEST_EQ(f(p), 1);

绑定对象构造函数

template<auto f, class U> function_ref(nontype_t<f>, U&&) noexcept;
效果

使用提供的指向成员的指针或指向成员函数的指针以及对要绑定到的对象的引用来构造 function_ref

如果 is_rvalue_reference_v<U&&> 为 false,则此重载才参与解析。

示例
struct point { int x = 1, y = 2; };

point p;
compat::function_ref<int()> f(compat::nontype_t<&point::x>{}, p);

BOOST_TEST_EQ(f(), 1);

绑定指针构造函数

template<auto f, class T> function_ref(nontype_t<f>, cv T*) noexcept;
效果

使用提供的指向成员的指针或指向成员函数的指针以及指向对象的指针来构造 function_ref

示例
struct point { int x = 1, y = 2; };

point p;
compat::function_ref<int()> f(compat::nontype_t<&point::x>{}, &p);

BOOST_TEST_EQ(f(), 1);

复制构造函数

function_ref(const function_ref&) noexcept = default;
效果

function_ref 是一个 TriviallyCopyable 类型。

成员函数

调用运算符

R operator()(ArgTypes...) const noexcept(noex);
效果

通过转发提供的参数来调用底层可调用对象。

赋值

复制赋值

function_ref& operator=(const function_ref&) noexcept = default;
template<class T> function_ref& operator=(T) = delete;
效果

如果满足以下条件,operator=(T) 参与重载解析

  • Tfunction_ref 不同

  • is_pointer_v<T>false

<boost/compat/integer_sequence.hpp>

描述

头文件 <boost/compat/integer_sequence.hpp> 实现了 C++14 实用程序 std::integer_sequencestd::index_sequencestd::make_integer_sequencestd::make_index_sequencestd::index_sequence_for

概要

namespace boost
{
namespace compat
{

template<class T, T... I> struct integer_sequence;

template<class T, T N> using make_integer_sequence = /*...*/;

template<std::size_t... I> using index_sequence = /*...*/;

template<std::size_t N> using make_index_sequence = /*...*/;

template<class... T> using index_sequence_for = /*...*/;

} // namespace compat
} // namespace boost

integer_sequence

template<class T, T... I> struct integer_sequence {};

make_integer_sequence

template<class T, T N> using make_integer_sequence = /*...*/;

make_integer_sequence<T, N>integer_sequence<T, 0, 1, 2, …​, N-1> 的别名。

index_sequence

template<std::size_t... I> using index_sequence = integer_sequence<std::size_t, I...>;

make_index_sequence

template<std::size_t N> using make_index_sequence = make_integer_sequence<std::size_t, N>;

index_sequence_for

template<class... T> using index_sequence_for = make_integer_sequence<std::size_t, sizeof...(T)>;

<boost/compat/invoke.hpp>

描述

头文件 <boost/compat/invoke.hpp> 实现了 C++17 函数 std::invoke、C++23 函数 std::invoke_r 以及相关的实用程序 invoke_result_tis_invocableis_invocable_ris_nothrow_invocableis_nothrow_invocable_r

invoke(f, a…​) 通常返回 f(a…​),但当 f 是指向成员的指针时,它会像返回 mem_fn(f)(a…​) 一样调用它。这允许函数、函数对象和指向成员的指针被 bind_front 等组件统一处理。

invoke_r<R>(f, a…​) 返回 invoke(f, a…​),并转换为 R

示例

struct X
{
    void f(int a, int b) const noexcept;
};

int main()
{
    X x;
    boost::compat::invoke(&X::f, x, 1, 2); // calls x.f(1, 2)
}

概要

namespace boost
{
namespace compat
{

template<class F, class... A> auto invoke(F&& f, A&&... a);

template<class F, class... A> using invoke_result_t = /*...*/;

template<class F, class... A> struct is_invocable;

template<class F, class... A> struct is_nothrow_invocable;

template<class R, class F, class... A> R invoke_r(F&& f, A&&... a);

template<class R, class F, class... A> struct is_invocable_r;

template<class R, class F, class... A> struct is_nothrow_invocable_r;

} // namespace compat
} // namespace boost

invoke

template<class F, class... A> auto invoke(F&& f, A&&... a) noexcept(/*...*/) -> /*...*/;
返回值
  • std::forward<F>(f)(std::forward<A>(a)…​),当 f 不是指向成员的指针时;

  • mem_fn(f)(std::forward<A>(a)…​),否则。

约束

返回表达式必须有效。

备注

返回类型为 decltype(r)noexcept 子句为 noexcept(noexcept(r)),其中 r 是返回表达式。

invoke_result_t

template<class F, class... A> using invoke_result_t =
  decltype( invoke(std::declval<F>(), std::declval<A>()...) );

is_invocable

template<class F, class... A> struct is_invocable: public /*...*/;

invoke(std::declval<F>(), std::declval<A>()…​) 是有效表达式时,is_invocable<F, A…​> 的基类是 std::true_type,否则为 std::false_type

is_nothrow_invocable

template<class F, class... A> struct is_nothrow_invocable: public /*...*/;

is_invocable<F, A…​>::valuefalse 时,is_nothrow_invocable<F, A…​> 的基类是 std::false_type,否则为 std::integral_constant<bool, noexcept(invoke(std::declval<F>(), std::declval<A>()…​))>

invoke_r

template<class R, class F, class... A> R invoke_r(F&& f, A&&... a) noexcept(/*...*/);
返回值
  • static_cast<R>(invoke(std::forward<F>(f), std::forward<A>(a)…​)),当 R 是(可能带有 cv 限定的) void 时;

  • invoke(std::forward<F>(f), std::forward<A>(a)…​),隐式转换为 R,否则。

约束

is_invocable<F, A…​>::value 必须为 true,并且如果 R 不是 cv void,则 std::is_convertible<invoke_result_t<F, A…​>, R>::value 必须为 true

备注

noexcept 子句为 noexcept(noexcept(static_cast<R>(invoke(std::forward<F>(f), std::forward<A>(a)…​))))

is_invocable_r

template<class R, class F, class... A> struct is_invocable: public /*...*/;

invoke_r<R>(std::declval<F>(), std::declval<A>()…​) 是有效表达式时,is_invocable_r<R, F, A…​> 的基类是 std::true_type,否则为 std::false_type

is_nothrow_invocable_r

template<class R, class F, class... A> struct is_nothrow_invocable: public /*...*/;

is_invocable_r<R, F, A…​>::valuefalse 时,is_nothrow_invocable<R, F, A…​> 的基类是 std::false_type,否则为 std::integral_constant<bool, noexcept(invoke_r<R>(std::declval<F>(), std::declval<A>()…​))>

<boost/compat/latch.hpp>

描述

头文件 <boost/compat/latch.hpp> 以可移植的方式实现了 C++20 <latch> 头文件。

latch 是一个单次使用的屏障,向下计数,实现一组线程之间的同步。计数器可以手动递减任何值,但递减到零以下会导致未定义的行为。等待者的最大数量被指定为 boost::compat::latch::max()

示例

std::ptrdiff_t const num_threads = 16;
boost::compat::latch l(num_threads);

std::vector<std::thread> threads;
for (int i = 0; i < num_threads; ++i) {
  threads.emplace_back([&l] {
    // do some preliminary work here...

    // block until all threads have reached this statement
    l.arrive_and_wait();

    // continue with further work...
  });
}

for (auto& t: threads) { t.join(); }

概要

namespace boost
{
namespace compat
{

class latch {
  explicit latch(std::ptrdiff_t expected);

  latch(latch const &) = delete;
  latch &operator=(latch const &) = delete;

  ~latch() = default;

  void count_down(std::ptrdiff_t n = 1);
  bool try_wait() const noexcept;
  void wait() const;
  void arrive_and_wait(std::ptrdiff_t n = 1);

  static constexpr std::ptrdiff_t max() noexcept;
};

} // namespace compat
} // namespace boost

构造函数

计数器构造函数

explicit latch(std::ptrdiff_t expected);
先决条件

expected >= 0 && expected <= boost::compat::latch::max().

效果

构造一个 latch,其内部计数器值为 expected

复制构造函数

latch(latch const &) = delete;

latch 不可复制或移动。

成员函数

count_down

void count_down(std::ptrdiff_t n = 1);
先决条件

n 不得大于当前内部计数器的值。

效果

将内部计数器递减 n

try_wait

bool try_wait() const noexcept;

返回一个布尔值,指示 latch 的内部计数器是否已达到 0 (true) 或未达到 (false)。

wait

void wait() const;

阻塞当前线程,直到内部计数器达到 0。

arrive_and_wait

void arrive_and_wait(std::ptrdiff_t n = 1);
先决条件

n 不得大于当前内部计数器的值。

效果

将内部计数器递减 n,如果计数器非零,则阻塞当前线程。

max

static constexpr std::ptrdiff_t max() noexcept;

返回一个实现定义的数字,表示最大等待者数量。当前为 PTRDIFF_MAX。

<boost/compat/mem_fn.hpp>

描述

头文件 <boost/compat/mem_fn.hpp> 实现了 C++11 函数 std::mem_fn

mem_fn(pm),其中 pm 是指向成员的指针,返回一个函数对象,该函数对象可用于使用函数调用语法调用成员函数或获取对数据成员的引用。

即使 std::mem_fn 是 C++11,但后来的标准对返回的函数对象提出了更严格的要求(它需要对 SFINAE 友好并正确传播 noexcept)。boost::compat::mem_fn 实现了这些更严格的要求。

示例

struct X
{
    void f(int a, int b) const noexcept;
};

int main()
{
    auto fn = boost::compat::mem_fn(&X::f);

    X x;
    fn(x, 1, 2); // calls x.f(1, 2)
}

概要

namespace boost
{
namespace compat
{

template<class M, class T> auto mem_fn(M T::* pm) noexcept;

} // namespace compat
} // namespace boost

mem_fn

template<class M, class T> auto mem_fn(M T::* pm) noexcept;
返回值

函数对象 fn,使得

  • M 是函数类型且 X 的类型为 T 或派生自 T 时,fn(x, a…​) 等价于 (x.*pm)(a…​)

  • M 是函数类型且 X 的类型不是 T 或派生自 T 时,fn(x, a…​) 等价于 ((*x).*pm)(a…​)

  • M 是对象类型且 X 的类型为 T 或派生自 T 时,fn(x) 等价于 x.*pm

  • M 是对象类型且 X 的类型不是 T 或派生自 T 时,fn(x) 等价于 (*x).*pm

<boost/compat/shared_lock.hpp>

描述

头文件 <boost/compat/shared_lock.hpp> 以可移植的方式实现了 C++14 std::shared_lock 类模板。

shared_lock 是一个 RAII 包装器,用于管理锁定和解锁提供的互斥锁,前提是它实现了 SharedLockable

这是 unique_lock 的共享模拟,并调用 lock_shared() 而不是 lock()

示例

#include <boost/compat/shared_lock.hpp>

shared_mutex m;

// acquire the lock by calling `m.lock_shared()`
// `m.unlock_shared()` is called automatically for us by `guard` now
boost::compat::shared_lock<shared_mutex> guard(m);
assert(guard.owns_lock());

概要

namespace boost {
namespace compat {

template <class Mutex>
class shared_lock;

template <class Mutex>
void swap( shared_lock<Mutex>& x, shared_lock<Mutex>& y ) noexcept;

template <class Mutex>
class shared_lock {
  using mutex_type = Mutex;

  shared_lock() noexcept = default;
  explicit shared_lock( mutex_type& m );
  shared_lock( mutex_type& m, std::defer_lock_t ) noexcept;
  shared_lock( mutex_type& m, std::try_lock_t );
  shared_lock( mutex_type& m, std::adopt_lock_t );

  ~shared_lock();

  shared_lock( const shared_lock& ) = delete;
  shared_lock& operator=( const shared_lock& ) = delete;

  shared_lock( shared_lock&& u ) noexcept;
  shared_lock& operator=( shared_lock&& u ) noexcept;

  void lock();
  bool try_lock();
  void unlock();

  void swap( shared_lock& u ) noexcept;
  mutex_type* release() noexcept;

  mutex_type* mutex() const noexcept;

  bool owns_lock() const noexcept;
  explicit operator bool() const noexcept;
};

} // namespace compat
} // namespace boost

构造函数

默认构造函数

shared_lock() noexcept = default;
后置条件

mutex() == nullptrowns_lock() == false

锁定构造函数

explicit shared_lock( mutex_type& m );
效果

调用 m.lock_shared()

后置条件

mutex() == std::addressof(m)owns_lock() == true

延迟构造函数

shared_lock( mutex_type& m, std::defer_lock_t ) noexcept;
后置条件

mutex() == std::addressof(m)owns_lock() == false

尝试锁定构造函数

shared_lock( mutex_type& m, std::try_lock_t );
效果

调用 m.try_lock_shared()

后置条件

mutex() == std::addressof(m)owns_lock() == res,其中 resm.try_lock_shared() 调用的结果。

采用构造函数

shared_lock( mutex_type& m, std::adopt_lock_t );
先决条件

m 必须由先前对 m.lock_shared() 的调用或成功调用 m.try_lock_shared() 持有。

后置条件

mutex() == std::addressof(m)owns_lock() == true

复制构造函数

shared_lock( const shared_lock& ) = delete;

shared_lock 不可复制。

移动构造函数

shared_lock( shared_lock&& u ) noexcept;
后置条件

mutex() == s.mutex()owns_lock() == s.owns_lock(),其中 s 是移动前 u 的状态。移动后 u.mutex() == nullptru.owns_lock() == false

赋值

复制赋值

shared_lock& operator=( const shared_lock& ) = delete;

shared_lock 不可复制。

移动赋值

shared_lock& operator=( shared_lock&& u ) noexcept;
效果

如果 owns_lock() == true,则调用 unlock()

后置条件

mutex() == s.mutex()owns_lock() == s.owns_lock(),其中 s 是移动前 u 的状态。移动后 u.mutex() == nullptru.owns_lock() == false

析构函数

~shared_lock();
效果

如果 owns_lock() == true,则调用 unlock()

成员函数

锁定

lock
void lock();
效果

调用 mutex()->lock_shared()

后置条件

owns_lock() == true.

抛出

mutex()->lock_shared() 引起的任何异常。当 mutex() == nullptr 时(带有 std::errc::operation_not_permitted)或 owns_lock() == true 时(带有 std::errc::resource_deadlock_would_occur)抛出 std::system_error

try_lock
bool try_lock();
效果

调用 mutex()->try_lock_shared()

后置条件

owns_lock() == res,其中 res = mutex()->try_lock_shared()

抛出

mutex()->try_lock_shared() 引起的任何异常。当 mutex() == nullptr 时(带有 std::errc::operation_not_permitted)或 owns_lock() == true 时(带有 std::errc::resource_deadlock_would_occur)抛出 std::system_error

unlock
void unlock();
效果

调用 mutex()->unlock_shared()

后置条件

owns_lock() == false.

抛出

如果 owns_lock() == false,则抛出 std::system_error(带有 std::errc::operation_not_permitted)。

修饰符

swap
void swap( shared_lock& u ) noexcept;
效果

交换 *thisu 的数据成员。

release
mutex_type* release() noexcept;
后置条件

mutex() == nullptrowns_lock() == false

返回值

mutex() 的先前值。

自由函数 swap
template <class Mutex>
void swap( shared_lock<Mutex>& x, shared_lock<Mutex>& y ) noexcept;
效果

通过 x.swap(y) 交换 xy 的数据成员。

观察器

mutex
mutex_type* mutex() const noexcept;
返回值

内部指针的值,nullptr 或互斥锁的地址。

owns_lock
bool owns_lock() const noexcept;
返回值

一个布尔值,指示互斥锁是否被当前 shared_lock 实例锁定。

布尔转换
explicit operator bool() const noexcept;
返回值

一个布尔值,指示互斥锁是否被当前 shared_lock 实例锁定。

<boost/compat/to_array.hpp>

描述

头文件 <boost/compat/to_array.hpp> 以可移植的方式实现了 C++20 std::to_array 函数,该函数存在于 <array> 头文件中。

to_array 从一维 C 数组创建一个 std::array,执行逐元素复制或移动。

示例

int input [] = {1, 2, 3};
std::array<int, 3> output = boost::compat::to_array(input);
assert((
    output == std::array<int, 3>{{1, 2, 3}}
));

概要

namespace boost
{
namespace compat
{

template <class T, std::size_t N>
constexpr std::array<remove_cv_t<T>, N> to_array(T (&a)[N]);

template <class T, std::size_t N>
constexpr std::array<remove_cv_t<T>, N> to_array(T (&&a)[N]);

} // namespace compat
} // namespace boost

to_array

template <class T, std::size_t N>
constexpr std::array<remove_cv_t<T>, N> to_array(T (&&a)[N]);
效果

通过复制 a 中的元素创建包含 N 个元素的数组。对于 0, …​, N-1 中的每个 i,从 a[i] 复制初始化输出数组中的第 i 个元素。

类型要求

std::is_constructible_v<remove_cv_t<T>, T&> && !std::is_array_v<T>。否则,重载形式不正确。

template <class T, std::size_t N>
constexpr std::array<remove_cvref_t<T>, N> to_array(T (&a)[N]);
效果

通过移动 a 中的元素创建包含 N 个元素的数组。对于 0, …​, N-1 中的每个 i,从 std::move(a[i]) 移动初始化输出数组中的第 i 个元素。

类型要求

std::is_constructible_v<remove_cv_t<T>, T&&> && !std::is_array_v<T>。否则,重载形式不正确。

<boost/compat/type_traits.hpp>

描述

头文件 <boost/compat/type_traits.hpp> 实现了标准头文件 <type_traits> 的一些 C++11 后添加项。

概要

#include <type_traits>

namespace boost
{
namespace compat
{

template<class T> using remove_const_t = typename std::remove_const<T>::type;

template<class T> using remove_cv_t = typename std::remove_cv<T>::type;

template<class T> using remove_reference_t = typename std::remove_reference<T>::type;

template<class T> using remove_cvref_t = remove_cv_t<remove_reference_t<T>>;

template<class T> using decay_t = typename std::decay<T>::type;

template<bool B, class T = void> using enable_if_t = typename std::enable_if<B, T>::type;

template<bool B, class T, class F> using conditional_t = typename std::conditional<B, T, F>::type;

template<class... T> using void_t = void;


} // namespace compat
} // namespace boost

本文档版权归 2023, 2024 Peter Dimov 及贡献者所有,并根据 Boost 软件许可协议 1.0 版 分发。