簡體   English   中英

如何使用std :: atomic <T> :: is_always_lock_free for SFINAE?

[英]How to use std::atomic<T>::is_always_lock_free for SFINAE?

如何在SFINAE中使用std::atomic<T>::is_always_lock_free 我有一個類模板MyClass<T> ,我想在2個實現之間切換,具體取決於std::atomic<T>::is_always_lock_free是否為true 這就是我所擁有的:

template<typename T, typename Enable = void>
class MyClass {
// Fallback implementation
};

template<typename T>
class MyClass<T, typename std::enable_if<std::atomic<T>::is_always_lock_free>::type> {
// Optimized implementation using std::atomic
};

現在,當我嘗試創建MyClass<SomeCustomClass>的實例時,我收到編譯器錯誤:

_Atomic不能應用於類型'SomeCustomClass',它不是可輕易復制的

它嘗試使用模板特化,但不使用回退實現,它根本不編譯。 有人可以解釋這里有什么問題嗎? 我如何獲得理想的結果?

你需要推遲檢查std::atomic<T>::is_always_lock_free直到你知道之后 T是平凡的可復制。 否則, atomic<T>是不正確的。

為此,有std::conjunction - 這是懶惰/短路:

template <typename T>
struct is_lock_free_impl
: std::integral_constant<bool, std::atomic<T>::is_always_lock_free> { };

template <typename T>
using is_lock_free = std::conjunction<
    std::is_trivially_copyable<T>,
    is_lock_free_impl<T>>;

現在,如果T不是可輕易復制的,那么這個特性會提前中止並產生false_type 如果它是可以輕易復制的,那么實例化atomic<T>是有效的,那么我們檢查這個特征。

在表達式std::atomic<T>::is_always_lock_free中, std::atomic<T>的瞬間失敗(對於不可挽回的可復制類型),並且這不是直接上下文,因此編譯失敗。 在這種情況下,您不需要實例化std::atomic<T> 如果std::atomic<T>合法,SFINAE會在這里工作,但std::atomic<T>::is_always_lock_free不會。

那么如何獲得理想的結果呢?

具有自定義特征:

#include <atomic>
#include <array>
#include <iostream>

class SomeClass { SomeClass& operator=(const SomeClass&) { return *this; } };

template<typename... T>
struct make_void { typedef void type; };

template<typename... T>
using void_t = typename make_void<T...>::type;

template<typename T, typename = void>
struct IsAlwaysLockFree
{
    static constexpr bool value = false;
};

template<typename T>
struct IsAlwaysLockFree<T, void_t<typename std::enable_if<!std::is_trivially_copyable<T>::value>::type>>
{
    static constexpr bool value = false;
};

template<typename T>
struct IsAlwaysLockFree<T, void_t<typename std::enable_if<std::is_trivially_copyable<T>::value>::type>>
{
    static constexpr bool value = std::atomic<T>::is_always_lock_free;
};

template<typename T, typename Enable = void>
class MyClass {
// Fallback implementation
public:
    MyClass(){ std::cout << "Fallback\n"; }
};

template<typename T>
class MyClass<T, typename std::enable_if<IsAlwaysLockFree<T>::value>::type> {
// Optimized implementation using std::atomic
public:
    MyClass(){ std::cout << "Optimized\n"; }
};

int main()
{
    MyClass<SomeClass> a;
    MyClass<std::array<int, 1024>> b;
    MyClass<int> c;
}

住在Coliru

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM