станд :: атомное <uint_least8_t> поведение

В системе с:

typedef unsigned char      uint8_t;
typedef unsigned short     uint16_t;

std::atomic<uint8_t>::is_always_lock_free // => false
std::atomic<uint16_t>::is_always_lock_free // => true

По моему мнению, тип

std::atomic<uint_least8_t>

будет 8 бит и не будет блокироваться.

Если да, то что я должен писать, если я хочу, чтобы атомный тип составлял не менее 8 бит и всегда блокировался? (при условии, что такой тип существует) Есть ли лучшая альтернатива, чем:

std::atomic<
    typename std::conditional<
        std::atomic<uint8_t>::is_always_lock_free, 
        uint8_t, 
        uint16_t
    >::type
>

(для простоты я не включил код, if std::atomic&lt;uint16_t> не заблокирован)

Ответ 1

Ну, материал шаблона немного грязный, но его использование довольно интуитивно:

#include <atomic>
#include <cstdint>
#include <iostream>

template <typename T, typename... others>
class first_lockfree
{
    // forward declare internal template
    template <bool, typename...> struct cond;

    // use this if is_always_lock_free == true
    template <typename condT, typename... condTs>
    struct cond<true, condT, condTs...>
    {
        // use first template argument as it is_always_lock_free
        using type = condT;
    };

    // use this if is_always_lock_free == false
    template <typename condT, typename... condTs>
    struct cond<false, condT, condTs...>
    {
        // use main template with first template parameter removed
        using type = typename first_lockfree<condTs...>::type;
    };

public:
    using type =typename cond<std::atomic<T>::is_always_lock_free, T, others...>::type;
};


int main(int, char**)
{
    using uint8_lockfree_t = first_lockfree<std::uint8_t, std::uint16_t, std::uint32_t, std::uint64_t>::type;

    std::cout <<  sizeof(uint8_lockfree_t) << std::endl;

    std::cout <<  std::atomic<std::uint8_t>::is_always_lock_free << std::endl;
    std::cout <<  std::atomic<std::uint16_t>::is_always_lock_free << std::endl;
    std::cout <<  std::atomic<std::uint32_t>::is_always_lock_free << std::endl;
    std::cout <<  std::atomic<std::uint64_t>::is_always_lock_free << std::endl;

    return 0;
}