C ++ 11支持所谓的"广义属性"以及两个标准属性carries_dependency
和deprecated
。 C ++ 14在表中添加了'some_attribute' attribute directive ignored
。但是,我找不到任何明确的标准在找到他们不知道的属性时要求做什么的实现。也许只是标准在这个问题上没有说什么。不过,我想知道。
在实践中,gcc和clang都会对可能被禁用的情况发出警告。特别是,gcc会发出警告-Wattributes
(unknown attribute 'some_attribute' ignored
),而clang会抱怨-Wunknown-attributes
(-Wattributes
)。但是,我还没有能够找到这些选项的文档;海湾合作委员会的Warning Options页面仅提及[[gnu::nonnull]] void my_function ( char * a , int * b );
,而对于Clang来说,似乎并不是一个类似的名单。
为什么我会问这个?嗯,一些特定于实现的属性很有趣。以GCC的nonnull
属性为例。我们可以用它来愉快地注释一些函数:
visibility
如果实现知道属性,一切都很好。但是如果它没有呢?我们可以期待什么?
忽略它,此行为由标准支持。我们可以继续添加我们在在线文档中找到的所有有趣属性。特别是,这样可以混合dllexport
和#if
而不会有#if BUILDING_DLL
#define DLLEXIMPORT dllexport
#else
#define DLLEXIMPORT dllimport
#endif
// even if MSVC doesn't support specifying dllexport this way, Clang does, and it can
// compile MSVC-compatible objects
[[gnu::visibility("default"),DLLEXIMPORT]] void api_function ();
个〜!
#if SOMETHING
#define ATTRIBUTE_GNU_NONNULL gnu::nonnull
#else
#define ATTRIBUTE_GNU_NONNULL
#endif
// if ATTRIBUTE_GNU_NONNULL is defined to nothing, all that happens is that we get
// an empty attribute list, which is 'standardly valid'
[[ATTRIBUTE_GNU_NONNULL]] void my_function ( char * a , int * b );
它抱怨它,这种行为得到了标准的支持。 D'哦!我们必须推出一些丑陋的机器来保护那些讨厌的实现方面的未知属性。
只有一个属性,这很容易,因为标准允许空属性列表:
#if SOMETHING
#define ATTRIBUTE_GNU_NONNULL gnu::nonnull
#else
#define ATTRIBUTE_GNU_NONNULL
#endif
#if SOMETHING
#define ATTRIBUTE_GNU_VISIBILITY( visibility_type ) gnu::visibility(#visibility_type)
#else
#define ATTRIBUTE_GNU_VISIBILITY( visibility_type )
#endif
// if any of the two macros is defined to nothing, it expands to [[,blah_blah]]
// or [[blah_blah,]] - both of which are invalid
[[ATTRIBUTE_GNU_NONNULL,ATTRIBUTE_GNU_VISIBILITY(default)]] void my_function
( char * a , int * b );
然而,有多个属性,事情变得更加棘手:
#if SOMETHING
#define ATTRIBUTES_GNU_NONNULL_AND_GNU_VISIBILITY( visibility_type ) \
gnu::nonnull,gnu::visibility(#visibility_type)
#else
#define ATTRIBUTES_GNU_NONNULL_AND_GNU_VISIBILITY( visibility_type )
#endif
[[ATTRIBUTES_GNU_NONNULL_AND_GNU_VISIBILITY(default)]] void my_function
( char * a , int * b );
想到的更为丑陋的解决方案是拥有组合属性的宏,如下所示:
:)
但我会为此{{1}}开枪。
因此,如果标准要求实现忽略未知属性,我可以选择我在在线文档中找到的所有相关属性而不用担心和没有丑陋的解决方案 - 因此我感兴趣。
答案 0 :(得分:2)
<强> 7.6.1 强> / 3
[...] 使用属性范围的令牌是有条件支持的,具有实现定义的行为。 [注意:每个实现都应该在属性范围标记中为attribute-namespace选择一个独特的名称。 - 后注]
<强> 7.6.1 强> / 5
对于本国际标准中未指定的属性标记,行为是实现定义的。
简而言之,答案是:检查编译器文档。
答案 1 :(得分:1)
[C++14: 7.6.1/5]:
对于本国际标准中未指定的属性标记,行为是实现定义的。
因此,如果您在遇到无法识别的属性时需要任何“保证”行为,则必须查阅实施文档。