简体   繁体   English

奇怪的解析行为 _Atomic 与模板

[英]Strange parsing behavior _Atomic with templates

//clang 3.8.0

#include <iostream>

template<typename T>
_Atomic T* get_atomic(T* val) {
    return reinterpret_cast<_Atomic T*>(val);
}

int main()
{

    volatile int val = 1;
    _Atomic volatile int* val_ptr = reinterpret_cast<_Atomic volatile int*>(&val);
    // works as expected
    std::cout << *val_ptr;
    // Fails due to "_Atomic cannot be applied to qualified type 'volatile int'"
    //std::cout << "Hello, world!\n" << *get_atomic(&val);
}

Why is there a discrepancy between the way the template expansion is parsed and the way that the explicit expansion is parsed?为什么解析模板扩展的方式和解析显式扩展的方式存在差异? They should be identical.它们应该是相同的。 Is there a way to ensure that _Atomic is treated as a qualifier in the presence of template arguments?有没有办法确保 _Atomic 在存在模板参数的情况下被视为限定符?

The keyword _Atomic comes from C (C11) and is not a keyword in C++.关键字_Atomic来自 C (C11) 并且不是 C++ 中的关键字。 In C++ atomics are specified via std::atomic .在 C++ 中,原子是通过std::atomic指定的。 The best would be not to mix syntactical concepts of the two languages.最好不要混合两种语言的句法概念。

If you have to mix code that accesses atomic data from both languages, you should deal with the atomic types such as std::atomic_int , or invent some macro interfaces similar to the following如果您必须混合使用两种语言访问原子数据的代码,您应该处理诸如std::atomic_int类的原子类型,或者发明一些类似于以下的宏接口

#ifdef __cplusplus
#define myAtomic(T) std::atomic< T >
#else
#define myAtomic(T) _Atomic(T)
#endif

On any reasonal platform these should be binary compatible.在任何合理的平台上,这些都应该是二进制兼容的。

This seems like a bug in either the spec or clang.这似乎是规范或 clang 中的一个错误。 To work around it, you can use the following trick to restore the qualifiers on the original type:要解决它,您可以使用以下技巧来恢复原始类型的限定符:

//clang 3.8.0

#include <iostream>

template<typename T>
struct Impl {
    T __a_value;
    using underlying_t = T;
    Impl(T val) : __a_value(val) {}
};

template <typename Tp_, typename Original_>                                                                                        
struct __annotate_with_qualifiers {                                                                                                 
  using __const_qualified = typename std::conditional<std::is_const<Original_>::value, const Tp_, Tp_>::type;                                 
  using __type = typename std::conditional<std::is_volatile<Original_>::value, volatile __const_qualified, __const_qualified>::type;          
};                                                                                                                                  

template<typename _Tp>                     
_LIBCPP_INLINE_VISIBILITY inline                                                                                                    
typename __annotate_with_qualifiers<_Atomic(typename _Tp::underlying_t), _Tp>::__type*            
__cxx_atomic_pointer_to_data(_Tp* __value) {                                                                                        
  return reinterpret_cast<typename __annotate_with_qualifiers<_Atomic(typename _Tp::underlying_t), _Tp>::__type*>(&__value->__a_value);                                                                                                       
}

template<typename T>
void print_val(const volatile T* val) {
    std::cout << "Const volatile " << *val << std::endl;
}

template<typename T>
void print_val(const T* val) {
    std::cout << "Const " << *val << std::endl;
}

template<typename T>
void print_val(volatile T* val) {
    std::cout << "Volatile " << *val << std::endl;
}

template<typename T>
void print_val(T* val) {
    std::cout << "Plain " << *val << std::endl;
}

int main()
{
    Impl<int> val(1);
    volatile Impl<int> val2(2);
    const Impl<int> val3(3);
    const volatile Impl<int> val4(4);
    print_val(__cxx_atomic_pointer_to_data(&val));
    print_val(__cxx_atomic_pointer_to_data(&val2));
    print_val(__cxx_atomic_pointer_to_data(&val3));
    print_val(__cxx_atomic_pointer_to_data(&val4));
}

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

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