Home > Net >  "Downcasting" a std::atomic_ref<T>
"Downcasting" a std::atomic_ref<T>

Time:10-06

Is it possible to downcast between std::atomic_ref<T> and std::atomic_ref<U> where U is a subclass of T?

I tried the following code which didn't work.

template<typename T>
std::atomic_ref<T> World::getComponentByID(componentInstanceId uuid) const {
    static componentTypeId key = stringHash(typeid(T).name());
    return components.at(uuid);
}

The template parameter T was position (a subclass of Component). components is a map of componentInstanceIds to Components .

error C2440: 'return': cannot convert from 'const std::atomic_ref<Component>' to 'std::atomic_ref<Position>

CodePudding user response:

Usage of atomic_ref this way does not make sense. (Even in lock_free cases that make sense in assembly language, the ISO C standard doesn't expose that functionality.)

As @Igor Tandetnik pointed out, "No subobject of an object referenced by an atomic_ref object may be concurrently referenced by any other atomic_ref object."

One of reasons this rule exists is that for non-lock-free atomic_ref it implements pool of mutexes, so having sub-object with different pointer value will get you into a different mutex for a subobject, or even a mutex from a different pool, or it may happen that sub-object is lock-free, but the bigger object is lock-based.

Additionally, possible pointer adjustments may defeat alignment, and it is mandatory for value referenced by atomic_ref to respect atomic_ref<T>::required_alignment.


atomic_ref is not a general purpose facility. Perhaps you just need to protect your objects with std::mutex or std::shared_mutex instead.

  • Related