Which Boost Features Overlap with C++11

Which Boost features overlap with C++11?

Replaceable by C++11 language features or libraries

  • Foreach → range-based for
  • Functional/Forward → Perfect forwarding (with rvalue references, variadic templates and std::forward)
  • In Place Factory, Typed In Place Factory → Perfect forwarding (at least for the documented use cases)
  • Lambda → Lambda expression (in non-polymorphic cases)
  • Local function → Lambda expression
  • Min-Max → std::minmax, std::minmax_element
  • Ratio → std::ratio
  • Static Assert → static_assert
  • Thread → <thread>, etc (but check this question).
  • Typeof → auto, decltype
  • Value initialized → List-initialization (§8.5.4/3)
  • Math/Special Functions → <cmath>, see the list below

    • gamma function (tgamma), log gamma function (lgamma)
    • error functions (erf, erfc)
    • log1p, expm1
    • cbrt, hypot
    • acosh, asinh, atanh

TR1 (they are marked in the documentation if those are TR1 libraries)

  • Array → std::array
  • Bind → std::bind
  • Enable If → std::enable_if
  • Function → std::function
  • Member Function → std::mem_fn
  • Random → <random>
  • Ref → std::ref, std::cref
  • Regex → <regex>
  • Result Of → std::result_of
  • Smart Ptr → std::unique_ptr, std::shared_ptr, std::weak_ptr (but boost::intrusive_ptr still cannot be replaced)
  • Swap (swapping arrays) → std::swap
  • Tuple → std::tuple
  • Type Traits → <type_traits>
  • Unordered → <unordered_set>, <unordered_map>

Features back-ported from C++11:

  • Atomic ← std::atomic
  • Chrono ← <chrono> (see below)
  • Move ← Rvalue references

Replaceable by C++17 language features:

  • String_ref → std::string_view
  • Filesystem → <filesystem> (Filesystem TS)
  • Optional → std::optional (Library Fundamentals TS v1)
  • Any → std::any (Library Fundamentals TS v1)
  • Math/Special Functions → <cmath> (Special Math IS), see the list below

    • beta function
    • (normal / associated / spherical) Legendre polynomials
    • (normal / associated) Legendre polynomials
    • Hermite polynomials
    • Bessel (J / Y / I / K) functions (Y is called Neumann function in C++)
    • spherical Bessel (j / y) functions
    • (incomplete / complete) elliptic integrals of (first / second / third kind)
    • Riemann zeta function
    • exponential integral Ei
  • Variant → std::variant (P0088R2)

The standard team is still working on it:

  • Math Common Factor → std::experimetal::gcd, lcm (Library Fundamentals TS v2)
  • Concept check → Concepts TS
  • Range → Range TS
  • Asio → Networking TS (sockets and timers only)
  • Multiprecision → Numerics TS
  • Coroutine/Coroutine2 → Coroutines TS

A large part of MPL can be trimmed down or removed using variadic templates. Some common use cases of Lexical cast can be replaced by std::to_string and std::stoX.

Some Boost libraries are related to C++11 but also have some more extensions, e.g. Boost.Functional/Hash contains hash_combine and related functions not found in C++11, Boost.Chrono has I/O and rounding and many other clocks, etc. so you may still want to take a look at the boost ones before really dismissing them.

Boost Libraries that made it into the C++ standard

There is no official list for this. You can find out about Boost incluence by reading the document that proposed the feature. Typically, it would say something like "This proposal is based on the Boost.XYZ library". Not necessarily in those words.

At least the following proposals were based, or heavily influenced on their respective boost library. Some of them were influenced by other implementations besides Boost. In some cases, it might equally appropriate to say that the boost library was influenced by the standard proposal. This is not necessarily a complete list:

<filesystem>
<shared_ptr>
<tuple>
<regex>
<thread>
<variant>
<optional>
<any>

Following proposals not (yet) accepted are similarly influenced. This list is probably even less complete:

<dl>
<process>
<stacktrace>
<networking> (C++20 should have a TS)
<static_vector><fixed_capacity_vector>
<expected><unexpected>
<safe>
<date_time>

In most cases, there are some differences between the boost library, because of lessons that were learned but could not be fixed in Boost due to backward compatibility, or because of desire to limit the scope of the proposal.

Why do I need Boost.SmartPtr for the C++ compiler that supports C++11 and later?

Why do I need Boost.SmartPtr for the C++ compiler that supports C++11 and later?

Because:

  1. You may need your program to compile with another compiler that doesn't support C++11 or later.
  2. You may not want to bother implementing make_unique yourself. Sure it's easy, but why do it when you can use an existing implementation?
  3. You may want to use one of the smart pointers provided by Boost.SmartPtr besides shared pointer.
  4. You may already have been using it, and don't want to pay for the effort of stopping using it.

Is there a container in Boost or C++11 which act as a queue but with unique elements?

This is called queue with conflation. The naive implementation is to use something like this:

std::set<your_key_t> unique;
std::queue<your_data_t> q;

void enqueue(your_data_t x) {
if (unique.insert(x.key).second) {
q.push(std::move(x));
}
}

your_data_t dequeue(your_data_t dflt) {
if (!q.empty()) {
your_data_t x = std::move(q.front()); q.pop();
unique.erase(q.front().key);
return x;
}
else return dflt;
}

A less naive implementation may be merging incoming data with the one in the queue in some non-trivial way (say overwriting) instead of just dropping updates.

C++ wrapper for boost/c++11

Your solution looks fine to me; the only problem will be (as Chet mentions) in the cases where the Boost and C++11 interfaces and/or implementations differ.

In fact, I do that in the Boost.Algorithms library (new in the upcoming 1.50 release)

namespace boost { namespace algorithm {
#if __cplusplus >= 201103L
using std::find_if_not; // Section 25.2.5
#else
template<typename InputIterator, typename Predicate>
InputIterator find_if_not ( InputIterator first, InputIterator last, Predicate p )
{
for ( ; first != last; ++first )
if ( !p(*first))
break;
return first;
}
#endif
}}

More elegant boost accumulation in C++11?

There are two methods I can think of, as follows:

std::vector< double > data = {2.1, 2.2, 3.3, 4.4, 5.5};
accumulator_set< double, features< tag::tail<left> > > acc(tag::tail<left>::cache_size = 4);

for_each(data.begin(), data.end(), [&acc](double y){ acc(y); });

or

std::vector< double > data = {2.1, 2.2, 3.3, 4.4, 5.5};
accumulator_set< double, features< tag::tail<left> > > acc(tag::tail<left>::cache_size = 4);

for (auto y : data)
acc(y);

boost::any typeid optimization for C++11

No, it's not guaranteed. This assert may trigger:

assert(&typeid(int) == &typeid(int));

While it would take a pretty stupid compiler to make that fire, it could happen. In practice, it will only fail when typeid's are being compared across dynamic library boundaries:

assert(&typeid_of_int_in_lib1() == &typeid_of_int_in_lib2());

This will almost certainly trigger.

Is it smart to replace boost::thread and boost::mutex with c++11 equivalents?

There are several differences between Boost.Thread and the C++11 standard thread library:

  • Boost supports thread cancellation, C++11 threads do not
  • C++11 supports std::async, but Boost does not
  • Boost has a boost::shared_mutex for multiple-reader/single-writer locking. The analogous std::shared_timed_mutex is available only since C++14 (N3891), while std::shared_mutex is available only since C++17 (N4508).
  • C++11 timeouts are different to Boost timeouts (though this should soon change now Boost.Chrono has been accepted).
  • Some of the names are different (e.g. boost::unique_future vs std::future)
  • The argument-passing semantics of std::thread are different to boost::thread --- Boost uses boost::bind, which requires copyable arguments. std::thread allows move-only types such as std::unique_ptr to be passed as arguments. Due to the use of boost::bind, the semantics of placeholders such as _1 in nested bind expressions can be different too.
  • If you don't explicitly call join() or detach() then the boost::thread destructor and assignment operator will call detach() on the thread object being destroyed/assigned to. With a C++11 std::thread object, this will result in a call to std::terminate() and abort the application.

To clarify the point about move-only parameters, the following is valid C++11, and transfers the ownership of the int from the temporary std::unique_ptr to the parameter of f1 when the new thread is started. However, if you use boost::thread then it won't work, as it uses boost::bind internally, and std::unique_ptr cannot be copied. There is also a bug in the C++11 thread library provided with GCC that prevents this working, as it uses std::bind in the implementation there too.

void f1(std::unique_ptr<int>);
std::thread t1(f1,std::unique_ptr<int>(new int(42)));

If you are using Boost then you can probably switch to C++11 threads relatively painlessly if your compiler supports it (e.g. recent versions of GCC on linux have a mostly-complete implementation of the C++11 thread library available in -std=c++0x mode).

If your compiler doesn't support C++11 threads then you may be able to get a third-party implementation such as Just::Thread, but this is still a dependency.



Related Topics



Leave a reply



Submit