![](/img/trans.png)
[英]Is std::atomic<T> safe with interrupts when std::atomic<T>::is_always_lock_free is false?
[英]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;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.