jeudi 14 janvier 2021

static_assert with std::atomic_store(std::shared_ptr

Because I need to target pre-c++20 compilers, I have this little gem:

template <typename T>
#ifdef __cpp_lib_atomic_shared_ptr
using Atom = std::atomic<T>;
#else
class Atom
{
private:
  using ValueType = typename std::remove_reference<decltype(*T{})>::type;

  std::shared_ptr<ValueType> ptr;

public:
  T load() { return std::atomic_load<ValueType>(&this->ptr); }
  void store(T p) { std::atomic_store<ValueType>(&this->ptr, p); }
  void reset() { this->store(nullptr); }
};
#endif

However, when I try to use this with a non-copyable type, I get:

/usr/include/c++/10/atomic: In instantiation of ‘struct std::atomic<std::vector<unsigned char> >’:
/usr/include/c++/10/atomic:1171:11:   required by substitution of ‘template<class _Tp> using __atomic_val_t = typename std::atomic::value_type [with _Tp = std::vector<unsigned char>]’
/usr/include/c++/10/atomic:1277:5:   required by substitution of ‘template<class _ITp> void std::atomic_store(volatile std::atomic<_ITp>*, std::__atomic_val_t<_ITp>) [with _ITp = std::vector<unsigned char>]’
foo.cpp:   required from ‘void {anonymous}::Atom<T>::store(T) [with T = std::shared_ptr<std::vector<unsigned char> >]’
foo.cpp:   required from here
/usr/include/c++/10/atomic:195:21: error: static assertion failed: std::atomic requires a trivially copyable type

Live demo.

It seems the compiler is aborting due to the static_assert before finding the specialization even though this isn't a viable overload candidate.

Is this expected behavior? Is there a "correct" work-around for this?

Right now I have this nasty little hack:

namespace std
{
template<> class atomic<vector<unsigned char>> {};
}

(Note: I'm aware that "don't #include <atomic>" works, which would suggest this is in fact not intended behavior. Unfortunately, I can't avoid <atomic> as it is being included via some other headers that my real code needs.)

Aucun commentaire:

Enregistrer un commentaire