c++booststdatomic

Why boost::atomic support non-trivial-copyable object?


boost::atomic requires T to be trivially copyable. But why the following code for boost::atomic<atom> works?


#include <chrono>
#include <iostream>
#include <memory>
#include <unordered_set>
#include <parallel/algorithm>
#include <boost/algorithm/cxx11/all_of.hpp>
#include <boost/atomic.hpp>
#include <boost/optional/optional.hpp>
#include <boost/range/algorithm/copy.hpp>
#include <boost/range/algorithm/count_if.hpp>
#include <boost/range/algorithm/remove_if.hpp>
#include <boost/range/algorithm/sort.hpp>
#include <boost/range/algorithm/unique.hpp>
#include <boost/range/irange.hpp>
#include <boost/range/numeric.hpp>


typedef uint32_t vint;  // Integer for vertex IDs

constexpr vint vmax = std::numeric_limits<vint>::max();  // Used as invalid ID

struct atom {
  boost::atomic<float> str;    // Total weighted degree of the community members
  boost::atomic<vint>  child;  // Last vertex that is merged to this vertex
  std::string c;
};

struct vertex {
  boost::atomic<atom> a;
  boost::atomic<vint> sibling;
  vint         united_child;
};

int main() {
    std::cout << "Is 'atom' trivially copyable? " 
              << std::boolalpha 
              << std::is_trivially_copyable<atom>::value
              << std::endl;

    return 0;
}

Reference: https://godbolt.org/z/vEv4jreK9


Solution

  • If you are not stuck on a C++98 or C++03, then there is no reason to use boost::atomic. C++11 added the same functionality standardized as std::atomic in <atomic>.

    And if you are using C++98 or C++03, then there is no way of compile-time checking whether a type is trivially-copyable. The necessary type trait was only added with C++11 and it is impossible to implement it with C++ core language features.

    So, in that case the template can't tell you at compile-time that you are giving the it a type that is not allowed. You will simply cause undefined behavior. Checking that the type is trivially-copyable is then your responsibility.

    You should really upgrade to C++11 or later. This is only a minor shortcoming of the old C++ language compared to many others.


    However, I just noticed that you are using some C++11 or later features. So I am confused why you are trying to use boost::atomic.

    Also, boost should normally compile-time check that the type is trivially-copyable if you compile in C++11 or later mode. However, you are using an old version of boost as well. The compile-time check wasn't yet implemented in 1.68 (presumably because there isn't much use of boost::atomic in C++11 mode). It was implemented with this commit for version 1.73.