Where can I use alignas() in C++11?

前端 未结 4 1709
不思量自难忘°
不思量自难忘° 2020-11-27 17:26

In an effort to standardize my code and make it more portable, I replaced

#ifdef __GNUC__
typedef __attribute__((aligned(16))) float aligned_block[4];
#else
         


        
相关标签:
4条回答
  • 2020-11-27 17:55

    I think you just placed the alignas in the wrong position. If you move it directly after the identifier, both GCC and Clang are happy and apply the alignment:

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

    this is also true if you use using, where the difference also becomes more apparent. Here are two versions that are not accepted by GCC (warning, alignment ignored):

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

    and here's the accepted one:

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

    I think that GCC applies

    7.1.3 The typedef specifier [dcl.typedef]

    2 A typedef-name can also be introduced by an alias-declaration. The identifier following the using keyword becomes a typedef-name and the optional attribute-specifier-seq following the identifier appertains to that typedef-name. It has the same semantics as if it were introduced by the typedef specifier. [...]

    (emphasis mine)

    The above is quite clear for using, the rules for typedef are spread through several paragraphs, including at the end of §8.3/1, where you find:

    8.3 Meaning of declarators [dcl.meaning]

    1 [...] The optional attribute-specifier-seq following a declarator-id appertains to the entity that is declared.

    (again, emphasis mine)


    Update: The above answer concentrated on where the alignas has to be placed, not on its exact meaning. After thinking about it some more, I still think that the above should be valid. Consider:

    7.6.2 Alignment Specifier [dcl.align]

    1An alignment-specifier may be applied to a variable or to a class data member, but it shall not be applied to a bit-field, a function parameter, an exception-declaration (15.3), or a variable declared with the register storage class specifier. An alignment-specifier may also be applied to the declaration or definition of a class (in an elaborated-type-specifier (7.1.6.3) or class-head (Clause 9), respectively) and to the declaration or definition of an enumeration (in an opaque-enum-declaration or enum-head, respectively (7.2)). An alignment-specifier with an ellipsis is a pack expansion (14.5.3).

    It lists cases where it can be clearly applied and it lists cases where it clearly can not be applied. The above question's example is neither.

    One could also argue that the type alias created by typedef or using is carrying the alignment specification as part of the aliased type. This alias can than be used to create a variable, etc. as allowed by 7.6.2p1 but not to create a variable with register, etc.

    In that sense I think that the attribute specifier is applied (in the sense of 7.6.2) in a deferred way and thus OPs example should still be valid when the alignment specification is put in the syntactically correct place.

    0 讨论(0)
  • 2020-11-27 18:15

    Try:

    typedef float alignas(16) aligned_block[4];
    
    0 讨论(0)
  • 2020-11-27 18:17

    You cannot apply an alignment to a typedef. In the C++ model of alignment specifiers, the alignment is an inseparable part of the type itself, and a typedef does not create a new type (it only provides a new name for an existing type) so it is not meaningful to apply an alignment specifier in a typedef declaration.

    From [dcl.align] (7.6.2)p1:

    An alignment-specifier may be applied to a variable or to a class data member [...]. An alignment-specifier may also be applied to the declaration or definition of a class (in an elaborated-type-specifier (7.1.6.3) or class-head (Clause 9), respectively) and to the declaration or definition of an enumeration (in an opaque-enum-declaration or enum-head, respectively (7.2)).

    These are the only places where the standard says an alignment-specifier (alignas(...)) may be applied. Note that this does not include typedef declarations nor alias-declarations.

    Per [dcl.attr.grammar] (7.6.1)p4:

    If an attribute-specifier-seq that appertains to some entity or statement contains an attribute that is not allowed to apply to that entity or statement, the program is ill-formed.

    This wording was intended to apply to alignas as well as the other forms of attribute that may appear within an attribute-specifier-seq, but was not correctly updated when alignment switched from being a "real" attribute to being a different kind of attribute-specifier-seq.

    So: your example code using alignas is supposed to be ill-formed. The C++ standard does not currently explicitly say this, but it also does not permit the usage, so instead it currently would result in undefined behavior (because the standard does not define any behavior for it).

    0 讨论(0)
  • 2020-11-27 18:18

    Draft C++11 standard http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf says about it (Alignment-specifier is of the form alignas ( assignment-expression )):

    7.6.2 Alignment specifier [dcl.align]

    1 An alignment-specifier may be applied to a variable or to a class data member, but it shall not be applied to a bit-field, a function parameter, the formal parameter of a catch clause (15.3), or a variable declared with the register storage class specifier. An alignment-specifier may also be applied to the declaration of a class or enumeration type. An alignment-specifier with an ellipsis is a pack expansion.

    I found this original proposal http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1877.pdf , it says:

    The alignment-specifier does not become part of the type, but it is possible to create a class type with aligned member variable(s).

    with this example:

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

    Looks like it's illegal to use it with typedef.

    0 讨论(0)
提交回复
热议问题