简体   繁体   English

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

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

How can I use std::atomic<T>::is_always_lock_free with SFINAE? 如何在SFINAE中使用std::atomic<T>::is_always_lock_free I have a class template MyClass<T> and I would like to switch between 2 implementations, depending on whether std::atomic<T>::is_always_lock_free is true . 我有一个类模板MyClass<T> ,我想在2个实现之间切换,具体取决于std::atomic<T>::is_always_lock_free是否为true This is what I have: 这就是我所拥有的:

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
};

Now, when I try to create an instance of MyClass<SomeCustomClass> , I get a compiler error: 现在,当我尝试创建MyClass<SomeCustomClass>的实例时,我收到编译器错误:

_Atomic cannot be applied to type 'SomeCustomClass' which is not trivially copyable _Atomic不能应用于类型'SomeCustomClass',它不是可轻易复制的

It tries to use the template specialization, but instead of using the fallback implementation, it doesn't compile at all. 它尝试使用模板特化,但不使用回退实现,它根本不编译。 Could someone kindly explain what's wrong here? 有人可以解释这里有什么问题吗? And how do I get the desired result? 我如何获得理想的结果?

You need to delay checking std::atomic<T>::is_always_lock_free until after you know that T is trivially copyable. 你需要推迟检查std::atomic<T>::is_always_lock_free直到你知道之后 T是平凡的可复制。 Otherwise, atomic<T> is ill-formed. 否则, atomic<T>是不正确的。

For that, there's std::conjunction - which is lazy / short-circuits: 为此,有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>>;

Now, this trait will abort early and yield false_type if T isn't trivially copyable. 现在,如果T不是可轻易复制的,那么这个特性会提前中止并产生false_type And if it is trivially copyable, then it's valid to instantiate atomic<T> , so then we check that trait. 如果它是可以轻易复制的,那么实例化atomic<T>是有效的,那么我们检查这个特征。

In the expression std::atomic<T>::is_always_lock_free the instantation of std::atomic<T> fails (for the non-triviably copyable types), and that's not immediate context, hence the compilation fails. 在表达式std::atomic<T>::is_always_lock_free中, std::atomic<T>的瞬间失败(对于不可挽回的可复制类型),并且这不是直接上下文,因此编译失败。 You need to not instantiate std::atomic<T> in that case. 在这种情况下,您不需要实例化std::atomic<T> SFINAE would have worked here if std::atomic<T> was legal, but std::atomic<T>::is_always_lock_free would not be. 如果std::atomic<T>合法,SFINAE会在这里工作,但std::atomic<T>::is_always_lock_free不会。

So how do I get the desired result? 那么如何获得理想的结果呢?

With a custom trait: 具有自定义特征:

#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;
}

Live on Coliru 住在Coliru

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM