Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/139.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何使用std::atomic<;T>;::SFINAE的锁总是免费的吗?_C++_C++17_Stdatomic - Fatal编程技术网

C++ 如何使用std::atomic<;T>;::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

如何在SFINAE中使用
std::atomic::is\u始终\u lock\u free
?我有一个类模板
MyClass
,我想在两个实现之间切换,这取决于
std::atomic::is\u always\u lock\u free
is
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{
//回退实现
};
模板
类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来检查它的可用性。