模板_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);
}
为什么模板扩展的解析方式与显式扩展的解析方式存在差异?它们应该是相同的。有没有办法确保在存在模板参数的情况下将_Atomic视为限定符?
关键字_Atomic
来自C(C11(,在C++中不是关键字。在C++原子是通过std::atomic
指定的。最好不要混合两种语言的语法概念。
如果你必须混合访问两种语言的原子数据的代码,你应该处理原子类型,如std::atomic_int
,或者发明一些类似于以下内容的宏接口
#ifdef __cplusplus
#define myAtomic(T) std::atomic< T >
#else
#define myAtomic(T) _Atomic(T)
#endif
在任何合理的平台上,这些都应该是二进制兼容的。
这似乎是规范或叮当声中的错误。若要解决此问题,可以使用以下技巧还原原始类型的限定符:
//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));
}
相关文章:
- .cpp和.h文件中的模板专用化声明
- C++模板来检查友元函数的存在
- 如何使用默认参数等选择模板专业化
- 模板参数替换失败,并且未完成隐式转换
- 具有默认模板参数的多态类的模板推导失败
- 部分定义/别名模板模板参数
- 模板-模板参数推导:三个不同的编译器三种不同的行为
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 如何在c++中为模板函数实例创建快捷方式
- 使用C++中的模板和运算符重载执行矩阵运算
- 有人能分解一下这个c++模板的语法吗
- 如何在c++17中制作一个模板包装器/装饰器
- 如何从 std::atomic 中提取指针 T<T>?
- 模板化建造师专业化
- 调用专用模板时出错"no matching function for call to [...]"
- 模板元程序查找相似的连续类型名称
- 如何在C++20中创建模板别名的推导指南
- 没有名称的C++模板参数
- 具有重复类型的C++可变模板
- 如何将enable-if与模板参数和参数包一起使用