Overview
Boost.Compat is a repository of C++11 implementations of standard components added in later C++ standards. Its target audience is Boost library authors whose libraries support a lower C++ standard, but wish to utilize a component added in a subsequent one.
The criteria for inclusion in Boost.Compat are as follows:
-
The implementation should be relatively simple and header-only.
-
The component must implement the standard functionality exactly, without deviations or extensions. This allows (but does not require) the implementation to be a simple
using
declaration in case the standard component is available. -
The component must not depend on any Boost libraries except Boost.Config, Boost.Assert, or Boost.ThrowException.
-
The component must not be a vocabulary type, visible in the library APIs. The user should never see a
boost::compat
type; the use of Compat types should be confined to library implementations.
Revision History
Changes in 1.87.0
-
Added
to_array.hpp
(contributed by Ruben Perez Hidalgo.)
Changes in 1.86.0
-
Added
bind_front.hpp
,bind_back.hpp
,invoke.hpp
,mem_fn.hpp
,integer_sequence.hpp
andtype_traits.hpp
. -
Added
function_ref.hpp
.
Changes in 1.83.0
-
Added
latch.hpp
, an implementation ofstd::latch
(contributed by Christian Mazakas.) -
Added
shared_lock.hpp
, a (partial) implementation ofstd::shared_lock
(contributed by Christian Mazakas.)
<boost/compat/bind_back.hpp>
Description
The header <boost/compat/bind_back.hpp>
implements the C++20 function
std::bind_back
.
bind_back
is a limited variant of std::bind
. It only supports binding
the last several parameters of a function object to specific argument values.
Example
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)
}
Synopsis
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 );
Returns: |
A function object |
<boost/compat/bind_front.hpp>
Description
The header <boost/compat/bind_front.hpp>
implements the C++20 function
std::bind_front
.
bind_front
is a limited variant of std::bind
. It only supports binding
the first several parameters of a function object to specific argument values.
Example
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)
}
Synopsis
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);
Returns: |
A function object |
<boost/compat/function_ref.hpp>
Description
The header <boost/compat/function_ref.hpp>
implements the C++26 class
std::function_ref
.
function_ref
is a lightweight polymorphic function wrapper that only stores a pointer to the supplied Callable object and a pointer to an unspecified function, meaning it does not participate in ownership of the Callable and does not allocate. All specializations of function_ref
satisfy TriviallyCopyable.
function_ref
supports every combination of const
and noexcept
and is useful for writing higher-order functions as
it can avoid a template parameter or an allocation (as std::function
is known for).
Example
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;
}
Synopsis
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
Constructors
Function Pointer Constructor
template<class F> function_ref(F* fn) noexcept;
Preconditions |
|
Effects |
Constructs a Calling the |
Object Constructor
template<class F> function_ref(F&& fn) noexcept;
Effects: |
Constructs a Calling the |
Pointer to Member Function Constructor
template<auto f> function_ref(nontype_t<f>) noexcept;
Effects: |
Constructs a Calling the |
Example: |
|
Bound Object Constructor
template<auto f, class U> function_ref(nontype_t<f>, U&&) noexcept;
Effects: |
Constructs a This overload only participates in resolution if |
Example: |
|
Bound Pointer Constructor
template<auto f, class T> function_ref(nontype_t<f>, cv T*) noexcept;
Effects: |
Constructs a |
Example: |
|
Copy Constructor
function_ref(const function_ref&) noexcept = default;
Effects: |
|
Member Functions
call operator
R operator()(ArgTypes...) const noexcept(noex);
Effects: |
Invokes the underlying Callable object by forwarding the supplied arguments. |
Assignment
Copy Assignment
function_ref& operator=(const function_ref&) noexcept = default;
template<class T> function_ref& operator=(T) = delete;
Effects: |
|
<boost/compat/integer_sequence.hpp>
Description
The header <boost/compat/integer_sequence.hpp>
implements the C++14 utilities
std::integer_sequence
, std::index_sequence
, std::make_integer_sequence
,
std::make_index_sequence
, and std::index_sequence_for
.
Synopsis
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>
is an alias for 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>
Description
The header <boost/compat/invoke.hpp>
implements the C++17 function
std::invoke
, the C++23 function std::invoke_r
, and the associated
utilities invoke_result_t
, is_invocable
, is_invocable_r
,
is_nothrow_invocable
, and is_nothrow_invocable_r
.
invoke(f, a…)
generally returns f(a…)
, but when f
is a pointer to
member, it invokes it as if by returning mem_fn(f)(a…)
. This allows
functions, function objects, and pointers to members to be treated uniformly
by components such as bind_front
.
invoke_r<R>(f, a…)
returns invoke(f, a…)
, converted to R
.
Example
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)
}
Synopsis
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(/*...*/) -> /*...*/;
Returns: |
|
Constraints: |
the return expression must be valid. |
Remarks: |
The return type is |
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 /*...*/;
The base class of is_invocable<F, A…>
is std::true_type
when invoke(std::declval<F>(), std::declval<A>()…)
is a valid expression, std::false_type
otherwise.
is_nothrow_invocable
template<class F, class... A> struct is_nothrow_invocable: public /*...*/;
The base class of is_nothrow_invocable<F, A…>
is std::false_type
when is_invocable<F, A…>::value
is false
, std::integral_constant<bool, noexcept(invoke(std::declval<F>(), std::declval<A>()…))>
otherwise.
invoke_r
template<class R, class F, class... A> R invoke_r(F&& f, A&&... a) noexcept(/*...*/);
Returns: |
|
Constraints: |
|
Remarks: |
The |
is_invocable_r
template<class R, class F, class... A> struct is_invocable: public /*...*/;
The base class of is_invocable_r<R, F, A…>
is std::true_type
when invoke_r<R>(std::declval<F>(), std::declval<A>()…)
is a valid expression, std::false_type
otherwise.
is_nothrow_invocable_r
template<class R, class F, class... A> struct is_nothrow_invocable: public /*...*/;
The base class of is_nothrow_invocable<R, F, A…>
is std::false_type
when is_invocable_r<R, F, A…>::value
is false
, std::integral_constant<bool, noexcept(invoke_r<R>(std::declval<F>(), std::declval<A>()…))>
otherwise.
<boost/compat/latch.hpp>
Description
The header <boost/compat/latch.hpp>
implements, in a portable way, the C++20
<latch>
header.
latch
is a single-use barrier which counts downwards, enabling synchronization
between a set of threads. The counter can be manually decremented by any value,
but decrementing below zero causes undefined behavior. The maximum number of waiters is
specified to be boost::compat::latch::max()
.
Example
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(); }
Synopsis
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
Constructors
Counter Constructor
explicit latch(std::ptrdiff_t expected);
Preconditions: |
|
Effects: |
Constructs a latch with an internal counter value of |
Copy Constructor
latch(latch const &) = delete;
latch
is not copyable or movable.
Member Functions
count_down
void count_down(std::ptrdiff_t n = 1);
Preconditions: |
|
Effects: |
Decrements the internal counter by |
try_wait
bool try_wait() const noexcept;
Returns a boolean indicating whether or not the latch’s internal counter has reached 0 (true
) or not (false
).
wait
void wait() const;
Blocks the current thread until the internal counter has reached 0.
arrive_and_wait
void arrive_and_wait(std::ptrdiff_t n = 1);
Preconditions: |
|
Effects: |
Decrements the internal counter by |
max
static constexpr std::ptrdiff_t max() noexcept;
Returns an implementation-defined number representing the maximum amount of waiters. Currently PTRDIFF_MAX.
<boost/compat/mem_fn.hpp>
Description
The header <boost/compat/mem_fn.hpp>
implements the C++11 function
std::mem_fn
.
mem_fn(pm)
, where pm
is a pointer to member, returns a function object
that can be used to invoke the member function, or obtain a reference to the
data member, using a function call syntax.
Even though std::mem_fn
is C++11, later standards place stricter
requirements on the returned function object (it needs to be SFINAE friendly
and propagate noexcept
correctly.) boost::compat::mem_fn
implements
these stricter requirements.
Example
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)
}
Synopsis
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;
Returns: |
A function object
|
<boost/compat/shared_lock.hpp>
Description
The header <boost/compat/shared_lock.hpp>
implements, in a portable way, the C++14
std::shared_lock
class template.
The class shared_lock
is a RAII wrapper that manages locking and unlocking
the provided Mutex, provided that it implements SharedLockable.
This is the shared analog of unique_lock
and calls lock_shared()
instead of lock()
.
Example
#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());
Synopsis
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
Constructors
Default Constructor
shared_lock() noexcept = default;
Postconditions: |
|
Locking Constructor
explicit shared_lock( mutex_type& m );
Effects: |
Calls |
Postconditions: |
|
Deferred Constructor
shared_lock( mutex_type& m, std::defer_lock_t ) noexcept;
Postconditions: |
|
Try-to-Lock Constructor
shared_lock( mutex_type& m, std::try_lock_t );
Effects: |
Calls |
Postconditions: |
|
Adopting Constructor
shared_lock( mutex_type& m, std::adopt_lock_t );
Preconditions: |
|
Postconditions: |
|
Copy Constructor
shared_lock( const shared_lock& ) = delete;
shared_lock
is not copyable.
Move Constructor
shared_lock( shared_lock&& u ) noexcept;
Postconditions: |
|
Assignment
Copy Assignment
shared_lock& operator=( const shared_lock& ) = delete;
shared_lock
is not copyable.
Move Assignment
shared_lock& operator=( shared_lock&& u ) noexcept;
Effects: |
If |
Postconditions: |
|
Destructor
~shared_lock();
Effects: |
If |
Member Functions
Locking
lock
void lock();
Effects: |
Calls |
Postconditions: |
|
Throws: |
Any exception caused by |
try_lock
bool try_lock();
Effects: |
Calls |
Postconditions: |
|
Throws: |
Any exception caused by |
unlock
void unlock();
Effects: |
Calls |
Postconditions: |
|
Throws: |
|
Modifiers
swap
void swap( shared_lock& u ) noexcept;
Effects: |
Swaps the data members of |
release
mutex_type* release() noexcept;
Postconditions: |
|
Returns: |
The previous value of |
Free Function swap
template <class Mutex>
void swap( shared_lock<Mutex>& x, shared_lock<Mutex>& y ) noexcept;
Effects: |
Swaps the data members of |
Observers
mutex
mutex_type* mutex() const noexcept;
Returns: |
The value of the internal pointer, either |
owns_lock
bool owns_lock() const noexcept;
Returns: |
A boolean indicating whether or not the mutex is locked by the current
|
boolean conversion
explicit operator bool() const noexcept;
Returns: |
A boolean indicating whether or not the mutex is locked by the current
|
<boost/compat/to_array.hpp>
Description
The header <boost/compat/to_array.hpp>
implements, in a portable way, the C++20
std::to_array
function, present in the <array>
header.
to_array
creates a std::array
from a single-dimensional C array,
performing an element-wise copy or move.
Example
int input [] = {1, 2, 3};
std::array<int, 3> output = boost::compat::to_array(input);
assert((
output == std::array<int, 3>{{1, 2, 3}}
));
Synopsis
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]);
Effects: |
Creates an array of |
Type requirements: |
|
template <class T, std::size_t N>
constexpr std::array<remove_cvref_t<T>, N> to_array(T (&a)[N]);
Effects: |
Creates an array of |
Type requirements: |
|
<boost/compat/type_traits.hpp>
Description
The header <boost/compat/type_traits.hpp>
implements some of the
post-C++11 additions to the standard header <type_traits>
.
Synopsis
#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
Copyright and License
This documentation is copyright 2023, 2024 Peter Dimov and contributors and is distributed under the Boost Software License, Version 1.0.