我在哪里可以在C ++ 11中使用alignas()?

时间:2013-04-03 13:39:06

标签: 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

typedef float alignas(16) aligned_block[4];

在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

而clang 3.2没有警告(即使-Weverything -Wno-c++98-compat -pedantic)。 所以我想知道上面的代码是否正确,更一般地说,alignas()可以放在哪里也不能放置。

EDIT(2013年4月)

该标准的相关文章是7.6.2,特别是7.6.2.1

  

对齐 - 说明符可以应用于变量或类数据成员,但不应用于位字段,函数参数,catch子句的形式参数(15.3)或变量使用寄存器存储类说明符声明。对齐说明符也可以应用于类或枚举类型的声明。带省略号的对齐说明符是包扩展(14.5.3)。

已经被Red XIII挖出来了。但是,我不够专业,不知道这对我上面的测试意味着什么。

如果clang接受我的属性这一事实意味着什么,或许值得一提的是,当尝试使用using指令而不是typedef时,clang也会抱怨。此外,与此问题的早期版本中的陈述相反,gcc不仅警告,而且实际上忽略了我对齐的愿望。

4 个答案:

答案 0 :(得分:26)

我认为你刚刚将alignas置于错误的位置。如果你在标识符后直接移动,GCC和Clang都很高兴并应用对齐方式:

typedef float aligned_block alignas(16) [4];
typedef float aligned_block [4] alignas(16);

如果使用using,情况也会如此,差异也会变得更明显。以下是GCC接受的两个版本(忽略警告,对齐):

using aligned_block = float alignas(16)[4];
using aligned_block = float[4] alignas(16);

这是接受的:

using aligned_block alignas(16) = float[4];

我认为GCC适用

  

7.1.3 typedef说明符[dcl.typedef]

     

2 alde-name 也可以通过 alias-declaration 引入。 using关键字后面的标识符成为 typedef-name 可选属性说明符-seq 位于< em> identifier 附属于 typedef-name 。它具有与typedef说明符引入的语义相同的语义。 [...]

(强调我的)

以上对using非常清楚,typedef的规则分散在几个段落中,包括§8.3/ 1的末尾,您可以找到:

  

8.3声明者的意义[dcl.meaning]

     

1 [...] declarator-id appertains之后的可选 attribute-specifier-seq 到声明的实体。

(再次强调我的)


更新:以上答案主要集中在 alignas必须放置,而不是其确切含义。在考虑了一些之后,我仍然认为上述内容应该是有效的。考虑:

  

7.6.2对齐说明[dcl.align]

     

1 alignment-specifier 可以应用于变量或类数据成员,但不应用于位字段,函数参数, exception-declaration (15.3),或使用register存储类说明符声明的变量。 alignment-specifier 也可以应用于类的声明或定义(在 elaborated-type-specifier (7.1.6.3)或 class-head中(第9条),以及枚举的声明或定义(分别在 opaque-enum-declaration enum-head 中)(7.2) ))。带有省略号的 alignment-specifier 是包扩展(14.5.3)。

它列出了可以明确应用的情况,并列出了明显无法 应用的情况。以上问题的例子都不是。

还可以说,typedefusing创建的类型别名将对齐规范作为别名类型的一部分。此别名可用于创建7.6.2p1允许的变量等,但不能用register等创建变量。

从这个意义上说,我认为属性说明符是以延迟的方式应用(在7.6.2的意义上),因此当对齐规范放在语法正确的位置时,OPs示例应该仍然有效。

答案 1 :(得分:11)

您无法将对齐应用于typedef。在对齐说明符的C ++模型中,对齐是类型本身不可分割的一部分,而typedef不会创建新类型(它只为现有类型提供新名称),因此它没有意义在typedef声明中应用对齐说明符。

来自 [dcl.align](7.6.2)p1

  

alignment-specifier 可以应用于变量或类数据成员[...]。 alignment-specifier 也可以应用于类的声明或定义(在 elaborated-type-specifier (7.1.6.3)或 class-head中(第9条),以及枚举的声明或定义(在 opaque-enum-declaration 中)   或 enum-head ,分别为(7.2))。

这些是标准中可以应用 alignment-specifier alignas(...))的唯一地方。请注意,此包含typedef声明,也不包含 alias-declaration

[dcl.attr.grammar](7.6.1)p4

  

如果属于某个实体或语句的 attribute-specifier-seq 包含不允许应用于该实体或语句的属性,则程序生病-formed。

此措辞旨在适用于alignas以及可能出现在属性说明符-seq 中的其他形式的属性,但在对齐切换时未正确更新作为另一种 attribute-specifier-seq 的“真实”属性。

所以:使用alignas的示例代码假设是错误的。 C ++标准目前没有明确说明这一点,但它也不允许使用,因此它当前会导致未定义的行为(因为标准没有为它定义任何行为)。

答案 2 :(得分:7)

草案C ++ 11标准http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf说明了它(Alignment-speci fi er的形式为alignas(赋值表达式)):

  

7.6.2对齐指示符[dcl.align]

     

1对齐规范可以应用于变量或类数据成员,但不应用   到一个位域,一个函数参数,一个catch子句的形式参数(15.3),或一个声明的变量   与寄存器存储类指定。对齐指定器也可以应用于声明   类或枚举类型。具有省略号的对齐规范是包扩展。

我找到了这个原始提案http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1877.pdf,它说:

  

alignment-specifier不会成为类型的一部分,但可以创建类类型   对齐成员变量。

这个例子:

// Wrong attempt: Listing 6)
typedef double align_by<0x10000> hwDoubleVector; // Error!
Void clear(hwDoubleVector &toClear, unsigned size);

将它与typedef一起使用似乎是违法的。

答案 3 :(得分:-1)

尝试:

typedef float alignas(16) aligned_block[4];