在努力规范我的代码,使其更加轻便,我取代
#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
而铛3.2不产生警告(即使-Weverything -Wno-c++98-compat -pedantic
)。 所以我想我的代码是否上面是正确的,更普遍,其中alignas()
不能放置。
EDIT(4月2013年):
从标准的相关条款是7.6.2,特别是7.6.2.1
对准说明符可以被应用到一个变量或一类数据成员,但它不应被施加到一个位字段,一个功能参数,catch子句(15.3)的形式参数,或变量与所声明的寄存器存储类说明。 对准说明符也可以被应用于一类或枚举类型的声明。 对准说明符以省略号是一包扩展(14.5.3)。
如已被红十三挖了出来。 不过,我不是专家,足以知道这是什么意思为我的测试上面。
如果铛接受我的属性的事实意味着什么,这也许值得一提的是,尝试使用时using
的,而不是一个指令typedef
,铛也抱怨。 此外,违背了这个问题的一个早期版本的说法,GCC不只是警告,但确实忽略了我的愿望一致。
你不能对齐应用到typedef
。 在对准说明符的C ++模型,对准是类型本身的一个不可分割的部分,和一个typedef
并不创建新的类型(它仅提供了用于一个现有类型的新名称),所以它是没有意义的施加对准说明符在typedef
声明。
从[dcl.align](7.6.2)P1:
对准说明符可以被应用到一个变量或一类数据成员[...]。 对准说明符还可以(分别在一个阐述型说明符 (7.1.6.3)或类头 (第9节),)应用于一类的声明或定义与以枚举的声明或定义(在分别的不透明-枚举声明或枚举头 ,(7.2))。
这是唯一的地方标准说的比对说明符 ( alignas(...)
可以应用。 请注意,这不包括typedef
声明,也不别名声明秒。
每[dcl.attr.grammar](7.6.1)P4:
如果属性说明符-SEQ是appertains一些实体或语句包含不允许适用于实体或声明的属性 ,是形成不良的程序。
该措辞旨在适用于alignas
以及可能的属性说明符序列中出现的其他形式的属性,但是当对准从一个“真正的”属性,切换到是别样的属性-没有正确地更新符-seq的 。
所以:使用示例代码alignas
被认为是病态的。 C ++标准目前不明确地这样说,但它也不允许使用,所以不是它目前会导致不确定的行为(因为标准没有定义任何的行为)。
我想你刚才放置的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所述的typedef名也可以通过一个别名声明来引入。 下面标识符 using
关键字成为typedef名以及可选的以下标识符 appertains到的typedef名称 属性说明符-SEQ。 它具有相同的语义,就好像它是由引进typedef
说明符。 [...]
(重点煤矿)
以上是相当明确的using
,该规则typedef
通过几段传播,包括在§8.3/ 1,你找到的结尾:
8.3含义说明符的[dcl.meaning]
1 [...]可选属性说明符-SEQ 以下说明符-ID appertains到被声明的实体。
(再次,重点煤矿)
更新:以上的答案集中在其中 alignas
必须放置,而不是它的确切含义。 想着它多一些之后,我仍然认为,上述应该是有效的。 考虑:
7.6.2对齐方式指定[dcl.align]
1 对准说明符可以被应用到一个变量或一类数据成员,但它不应被施加到一个位字段,一个功能参数,一个例外声明 (15.3),或一个变量声明的register
存储类说明。 对准说明符还可以(分别在一个阐述型说明符 (7.1.6.3)或类头 (第9节),)应用于一类的声明或定义与以枚举的声明或定义(在分别的不透明-枚举声明或枚举头 ,(7.2))。 对准说明符以省略号是一包扩展(14.5.3)。
它列出了在那里可以清楚地应用于案件并列出它显然不能适用的情况。 上述问题的例子是既不。
人们还可以认为,类型别名通过创建typedef
或using
携带对准说明书中作为别名类型的一部分。 此别名能够比被用来创建一个变量等所允许的7.6.2p1但不与创建一个变量register
等
在这个意义上,我认为该属性说明符的递延方式应用(在7.6.2的意义上),因此有机磷农药的例子应该仍然有效当对准规范放在语法正确的地方。
C ++草案标准11 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf说一下(取向-SPECI音响ER的形式为alignas
(赋值表达式) ):
7.6.2对齐SPECI音响ER [dcl.align]
1对准-SPECI音响ER可以被施加到一个变量或一类数据成员,但它不应被施加到比特音响场,一个功能参数,catch子句(15.3)的形式参数,或变量与声明寄存器存储类SPECI网络呃。 对准-SPECI音响ER也可以应用于一类或枚举类型的声明。 以省略号对准-SPECI网络ER是一包的扩展。
我发现这个原来的建议http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1877.pdf ,它说:
对准说明符不成为类型的一部分,但也可以创建一个类类型对齐的成员变量(多个)。
这个例子:
// Wrong attempt: Listing 6)
typedef double align_by<0x10000> hwDoubleVector; // Error!
Void clear(hwDoubleVector &toClear, unsigned size);
看起来它是非法的与使用它typedef
。
尝试:
typedef float alignas(16) aligned_block[4];