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
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