C++ 在C++;11?
为了使我的代码标准化并使其更具可移植性,我将C++ 在C++;11?,c++,c++11,alignment,alignas,C++,C++11,Alignment,Alignas,为了使我的代码标准化并使其更具可移植性,我将 #ifdef __GNUC__ typedef __attribute__((aligned(16))) float aligned_block[4]; #else typedef __declspec(align(16)) float aligned_block[4]; #endif 与 在C++11中。然而,gnu(4.8)不喜欢这一点,但抱怨 test.cc:3:9: warning: attribute ignored [-Wattribu
#ifdef __GNUC__
typedef __attribute__((aligned(16))) float aligned_block[4];
#else
typedef __declspec(align(16)) float aligned_block[4];
#endif
与
在C++11中。然而,gnu(4.8)不喜欢这一点,但抱怨
test.cc:3:9: warning: attribute ignored [-Wattributes]
typedef float alignas(16) aligned_block[4];
^
test.cc:3:9: note: an attribute that appertains to a type-specifier is ignored
而Clang3.2不会产生任何警告(即使使用-Weverything-Wno-c++98 compat-pedantic
)。
因此,我想知道我上面的代码是否正确,更一般地说,哪里可以放置alignas()
编辑(2013年4月):
本标准的相关条款为7.6.2,特别是7.6.2.1
对齐说明符可以应用于变量或类数据成员,但不能应用于位字段、函数参数、catch子句(15.3)的形式参数或用寄存器存储类说明符声明的变量。对齐说明符也可以应用于类或枚举类型的声明。带有省略号的对齐说明符是块扩展(14.5.3)
已经被红十三挖出来了。然而,我还不够专业,不知道这对我的上述测试意味着什么
如果clang接受我的属性这一事实意味着什么,那么可能值得一提的是,当试图使用using
指令而不是typedef
时,clang也会抱怨。此外,与此问题的早期版本中的声明相反,gcc不仅发出警告,而且确实忽略了我的对齐愿望。C++11标准草案对此进行了说明(对齐规范的形式为alignas
(赋值表达式)):
7.6.2校准规范[dcl.校准]
1校准规范可应用于变量或类数据成员,但不得应用
对于位字段,函数参数、catch子句(15.3)的形式参数或声明的变量
使用寄存器存储类规范。线形规范也可应用于路线声明
类或枚举类型。带有省略号的对齐规范是一个包扩展
我找到了这个原始提案,上面写着:
对齐说明符不会成为类型的一部分,但可以创建类类型
使用对齐的成员变量
在这个例子中:
// Wrong attempt: Listing 6)
typedef double align_by<0x10000> hwDoubleVector; // Error!
Void clear(hwDoubleVector &toClear, unsigned size);
//错误的尝试:清单6)
typedef通过hwdublevector进行双对齐;//错误!
无效清除(HWDubleVector&toClear,无符号大小);
将其与typedef
一起使用似乎是非法的,请尝试:
typedef float alignas(16) aligned_block[4];
我想您刚刚把
对齐设置为放错位置了。如果将其直接移动到标识符之后,GCC和Clang都会很高兴并应用对齐方式:
typedef float aligned_block alignas(16) [4];
typedef float aligned_block [4] alignas(16);
如果您使用
使用
,也会出现这种情况,其中的差异也会变得更加明显。以下是GCC不接受的两个版本(警告,忽略对齐):
这是公认的一个:
using aligned_block alignas(16) = float[4];
我认为GCC适用
7.1.3类型定义说明符[dcl.typedef]
2还可以通过别名声明引入typedef名称。using
关键字后面的标识符成为typedef名称,标识符后面的可选属性说明符seq属于该typedef名称。它的语义与由typedef
说明符引入的语义相同。[……]
(强调矿山)
上述内容对于使用的非常清楚,typedef
的规则分布在多个段落中,包括§8.3/1末尾,您可以在其中找到:
8.3声明人的含义【dcl.含义】
1[…]声明器id后面的可选属性说明符seq与声明的实体相关
(再次强调我的)
更新:上述答案集中在必须放置对齐的位置,而不是其确切含义。再想一想,我仍然认为上面的说法应该是正确的。考虑:
7.6.2对齐说明符[dcl.align]
1对齐说明符可以应用于变量或类数据成员,但不能应用于位字段、函数参数、异常声明(15.3)或使用寄存器存储类说明符声明的变量。对齐说明符也可以应用于类的声明或定义(分别在详细的类型说明符(7.1.6.3)或类头(第9条)中)和枚举的声明或定义(分别在不透明的枚举声明或枚举头(7.2)中)。带有省略号的对齐说明符是块扩展(14.5.3)
它列出了可以明确应用的情况,也列出了无法明确应用的情况。上述问题的例子两者都不是
也有人可能认为,由typedef
或使用创建的类型别名将对齐规范作为别名类型的一部分。此别名可用于创建7.6.2p1所允许的变量等,但不能创建带有寄存器的变量等
从这个意义上说,我认为属性说明符是以延迟的方式应用的(在7.6.2的意义上),因此,当对齐规范放在语法正确的位置时,OPs示例应该仍然有效。您不能将对齐应用到typedef
。在对齐模式的C++模型中,对齐是类型本身的不可分割的部分,而 TyPulf不创建新类型(它只为现有类型提供新名称),因此在“<代码> TyPosif< /Cord>Nealth.< /P>中应用对齐说明符是没有意义的”。
从[dcl.align](7.6.2)p1开始:
对齐说明符可以应用于变量或类数据成员[…]。对齐说明符也可应用于类的声明或定义(在详细的类型说明符(7.1.6.3)或类头(第
using aligned_block = float alignas(16)[4];
using aligned_block = float[4] alignas(16);
using aligned_block alignas(16) = float[4];