首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用std::atomic<T>::is_always_lock_free进行SFINAE?

如何使用std::atomic<T>::is_always_lock_free进行SFINAE?
EN

Stack Overflow用户
提问于 2017-10-25 19:31:24
回答 2查看 890关注 0票数 3

如何将std::atomic<T>::is_always_lock_free与SFINAE结合使用?我有一个类模板MyClass<T>,我希望在两个实现之间切换,这取决于std::atomic<T>::is_always_lock_free是否是true。这就是我所拥有的:

代码语言:javascript
复制
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‘类型

它尝试使用模板专门化,但是它完全不编译,而不是使用回退实现。有人能解释一下这是怎么回事吗?我怎样才能得到想要的结果?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-10-25 19:53:27

您需要延迟检查std::atomic<T>::is_always_lock_free,直到您知道T是可以复制的。否则,atomic<T>是畸形的.

为此,有一个std::conjunction --它是懒惰/短路的--电路:

代码语言:javascript
复制
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>>;

现在,如果false_type不是可以复制的,那么这个特性就会提前终止并产生T。如果它是可以复制的,那么实例化atomic<T>是有效的,所以我们检查这个特性。

票数 10
EN

Stack Overflow用户

发布于 2017-10-25 19:50:56

在表达式std::atomic<T>::is_always_lock_free中,std::atomic<T>的实例化失败(对于不可复制的类型),这不是直接上下文,因此编译失败。在这种情况下,不需要实例化std::atomic<T>。如果std::atomic<T>是合法的,SFINAE会在这里工作,但std::atomic<T>::is_always_lock_free不会。

那么我怎样才能得到预期的结果呢?

具有风俗特点的:

代码语言:javascript
复制
#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;
}

住在Coliru

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46940680

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档