如何使用 std::atomic<T>::is_always_lock_free for SFINAE?
How to use std::atomic<T>::is_always_lock_free for SFINAE?
如何将std::atomic<T>::is_always_lock_free
与SFINAE一起使用?我有一个类模板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 << "Fallbackn"; }
};
template<typename T>
class MyClass<T, typename std::enable_if<IsAlwaysLockFree<T>::value>::type> {
// Optimized implementation using std::atomic
public:
MyClass(){ std::cout << "Optimizedn"; }
};
int main()
{
MyClass<SomeClass> a;
MyClass<std::array<int, 1024>> b;
MyClass<int> c;
}
住在科里鲁
相关文章:
- 尝试构建"lock-free"数据结构C++
- 为什么 c++11 std::lock 和 std::scoped_lock 至少需要 2 个参数?
- 为什么"weak.lock()"返回"nullptr" "auto weak=std::make_shared<int>(42);"的定义?
- DRD 报告"conflicting load" std::mutex::lock 上的错误
- 在 std::tie 中使用 std::weak_ptr::lock()
- std::lock_guard 怎么可能比 std::mutex::lock() 更快?
- std::mutex::lock() 产生奇怪(和不必要的)ASM 代码
- "lock cmpxchg"如何在装配中工作?
- std::lock 仍然导致死锁
- 在任何地方对C++中所有并行线程中的所有锁定和解锁实例使用相同的 std::mutex 和 lock 对象
- 我们是否需要对多线程 x32 系统使用 lock 来读取或写入 uint32_t 变量
- 使用Mutex,lock_guard,在课堂中正确地lock
- 如何在Visual Studio 2019中修复"[member variable that is a vulkan struct] is uninitialized. Always initiali
- 使用代码调整删除"comparison is always false"警告
- 符合要求的编译器应该能够优化哪些指针比较以"always false"?
- 当我调用lock()时,为什么std :: mutex会引发异常
- QPixmap,如何确保它是'always on top'
- mutex.lock vs unique_lock
- 在Linux上使用QT,有没有办法禁用"Always on Top"?
- 使用 std::lock (c++11) 的大量 CPU 负载