概述
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.hpp
、bind_back.hpp
、invoke.hpp
、mem_fn.hpp
、integer_sequence.hpp
和type_traits.hpp
。 -
添加了
function_ref.hpp
。
1.83.0 版本的更改
-
添加了
latch.hpp
,std::latch
的实现(由 Christian Mazakas 贡献)。 -
添加了
shared_lock.hpp
,std::shared_lock
的(部分)实现(由 Christian Mazakas 贡献)。
<boost/compat/bind_back.hpp>
描述
头文件 <boost/compat/bind_back.hpp>
实现了 C++20 函数 std::bind_back
。
bind_back
是 std::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 );
返回值 |
函数对象 |
<boost/compat/bind_front.hpp>
描述
头文件 <boost/compat/bind_front.hpp>
实现了 C++20 函数 std::bind_front
。
bind_front
是 std::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);
返回值 |
函数对象 |
<boost/compat/function_ref.hpp>
描述
头文件 <boost/compat/function_ref.hpp>
实现了 C++26 类 std::function_ref
。
function_ref
是一个轻量级的多态函数包装器,它仅存储指向提供的 可调用 对象的指针和指向未指定函数的指针,这意味着它不参与可调用对象的所有权,也不分配内存。function_ref
的所有特化都满足 TriviallyCopyable。
function_ref
支持 const
和 noexcept
的每种组合,并且对于编写高阶函数非常有用,因为它可以避免模板参数或分配(如 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;
先决条件 |
|
效果 |
构造一个 调用 |
对象构造函数
template<class F> function_ref(F&& fn) 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;
效果 |
|
成员函数
调用运算符
R operator()(ArgTypes...) const noexcept(noex);
效果 |
通过转发提供的参数来调用底层可调用对象。 |
赋值
复制赋值
function_ref& operator=(const function_ref&) noexcept = default;
template<class T> function_ref& operator=(T) = delete;
效果 |
如果满足以下条件,
|
<boost/compat/integer_sequence.hpp>
描述
头文件 <boost/compat/integer_sequence.hpp>
实现了 C++14 实用程序 std::integer_sequence
、std::index_sequence
、std::make_integer_sequence
、std::make_index_sequence
和 std::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_t
、is_invocable
、is_invocable_r
、is_nothrow_invocable
和 is_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(/*...*/) -> /*...*/;
返回值 |
|
约束 |
返回表达式必须有效。 |
备注 |
返回类型为 |
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…>::value
为 false
时,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(/*...*/);
返回值 |
|
约束 |
|
备注 |
|
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…>::value
为 false
时,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);
先决条件 |
|
效果 |
构造一个 latch,其内部计数器值为 |
复制构造函数
latch(latch const &) = delete;
latch
不可复制或移动。
成员函数
count_down
void count_down(std::ptrdiff_t n = 1);
先决条件 |
|
效果 |
将内部计数器递减 |
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);
先决条件 |
|
效果 |
将内部计数器递减 |
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;
返回值 |
函数对象
|
<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;
后置条件 |
|
锁定构造函数
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( const shared_lock& ) = delete;
shared_lock
不可复制。
移动构造函数
shared_lock( shared_lock&& u ) noexcept;
后置条件 |
|
赋值
复制赋值
shared_lock& operator=( const shared_lock& ) = delete;
shared_lock
不可复制。
移动赋值
shared_lock& operator=( shared_lock&& u ) noexcept;
效果 |
如果 |
后置条件 |
|
析构函数
~shared_lock();
效果 |
如果 |
成员函数
锁定
lock
void lock();
效果 |
调用 |
后置条件 |
|
抛出 |
由 |
try_lock
bool try_lock();
效果 |
调用 |
后置条件 |
|
抛出 |
由 |
unlock
void unlock();
效果 |
调用 |
后置条件 |
|
抛出 |
如果 |
修饰符
swap
void swap( shared_lock& u ) noexcept;
效果 |
交换 |
release
mutex_type* release() noexcept;
后置条件 |
|
返回值 |
|
自由函数 swap
template <class Mutex>
void swap( shared_lock<Mutex>& x, shared_lock<Mutex>& y ) noexcept;
效果 |
通过 |
观察器
mutex
mutex_type* mutex() const noexcept;
返回值 |
内部指针的值, |
owns_lock
bool owns_lock() const noexcept;
返回值 |
一个布尔值,指示互斥锁是否被当前 |
布尔转换
explicit operator bool() const noexcept;
返回值 |
一个布尔值,指示互斥锁是否被当前 |
<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]);
效果 |
通过复制 |
类型要求 |
|
template <class T, std::size_t N>
constexpr std::array<remove_cvref_t<T>, N> to_array(T (&a)[N]);
效果 |
通过移动 |
类型要求 |
|
<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 版 分发。