C++ 如何使用std::atomic<;T>;::SFINAE的锁总是免费的吗?
如何在SFINAE中使用C++ 如何使用std::atomic<;T>;::SFINAE的锁总是免费的吗?,c++,c++17,stdatomic,C++,C++17,Stdatomic,如何在SFINAE中使用std::atomic::is\u始终\u lock\u free?我有一个类模板MyClass,我想在两个实现之间切换,这取决于std::atomic::is\u always\u lock\u freeistrue。这就是我所拥有的: template<typename T, typename Enable = void> class MyClass { // Fallback implementation }; template<typename
std::atomic::is\u始终\u lock\u free
?我有一个类模板MyClass
,我想在两个实现之间切换,这取决于std::atomic::is\u always\u lock\u free
istrue
。这就是我所拥有的:
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{
//回退实现
};
模板
类MyClass{
//使用std::atomic优化实现
};
现在,当我尝试创建MyClass
的实例时,我得到一个编译器错误:
_原子不能应用于不可复制的类型“SomeCustomClass”
它尝试使用模板专门化,但不使用回退实现,它根本不编译。有人能解释一下这里出了什么问题吗?如何获得所需的结果?在表达式
std::atomic::is_always_lock_free
中,std::atomic
的实例化失败(对于不可复制的类型),而这不是直接上下文,因此编译失败。在这种情况下,不需要实例化std::atomic
。如果std::atomic
是合法的,SFINAE会在这里工作,但std::atomic::is\u always\u lock\u 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;
}
#include您需要延迟检查std::atomic::is_always_lock_free
,直到您知道T
是可复制的。否则,原子的
格式不正确
对于这一点,有-这是懒惰/短路:
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>>;
模板
结构是_lock _free _impl
:std::积分_常数{};
模板
使用is_lock_free=std::conjunction<
std::是可复制的,
锁是自由的吗;
现在,如果T
不是可复制的,那么这个特性将很早中止并产生false\u type
。如果它是可复制的,那么实例化原子
是有效的,所以我们检查这个特性 你不能有一个std::atomic
,其中SomeCustomClass
是不可复制的。这就是为什么会出现这样的错误,我知道……但为什么这不只是替换失败,导致常规模板的回退?在表达式std::atomic::is_always_lock_free
中,std::atomic
的实例化失败(对于不可复制的类型),而这不是直接上下文,因此编译失败。在这种情况下,不需要实例化std::atomic
。如果std::atomic
合法,SFINAE会在这里工作,但是std::atomic::is_always\u lock\u free
不会。@basteln您还有一个问题,std::atomic::is_always\u lock\u free
仅在C++17及以上版本中可用。@raket1111对。我会使用ifdef来检查它的可用性。