首先,值得注意的是“const”是“pure”的更严格版本,因此如果编译器没有实现“const”,“pure”可以用作后备。
正如其他人所提到的,MSVC 并没有任何类似的东西,但是很多编译器都采用了 GCC 语法,包括许多没有定义的语法__GNUC__
(有些有时会,有时不会,取决于标志)。
- GCC
自 2.96+ 起
支持pure ,自 2.5.0 起支持const
,以防您想检查版本。
- Clang 两者都支持;您可以使用
__has_attribute(pure)
and
__has_attribute(const)
来检测它们,但仅依靠 clang setting 可能就可以了__GNUC__
。这还包括基于 clang 的编译器,例如 emscripten 和 XL C/C++ 13+。
- 英特尔 C/C++ 编译器两者都支持,但它们的文档很糟糕,所以我不知道它们是什么时候添加的。16.0+当然是安全的。
- Oracle Developer Studio 12.2+支持这两者。
- ARM C/C++ 编译器 4.1+(可能更旧)同时支持
pure
和
const
- IBM XL C/C++ 至少从10.1开始。
- TI 8.0+
- 带有 --gcc 的TI 7.3+
(使用 检测
__TI_GNU_ATTRIBUTE_SUPPORT__
)支持两者。
- PGI 没有记录它(AFAICT),但两个属性都有效(或至少被默默地忽略)。17.10+ 是安全的,尽管它们可能已经接受了更长的时间。
其中,clang 总是定义__GNUC__
和朋友(目前到 4.2,IIRC)。默认情况下,英特尔定义__GNUC__
(尽管可以使用 -no-gcc 抑制),就像 C++ 模式下的 PGI 一样(但不在 C 模式下)。您必须手动检查其他人。
Oracle Developer Studio 也支持 pragma,因为它被称为Forte Developer 6。它们的使用方式略有不同,因为它们要求您指定函数名称:
/* pure: */
#pragma does_not_write_global_data (funcname)
/* const; SPARC-only until 12.2 */
#pragma no_side_effect (funcname)
TI 6.0+(至少)#pragma FUNC_IS_PURE;
仅支持 C++ 模式下的编译指示。在 C 模式下,它是#pragma FUNC_IS_PURE(funcname);
.
其中大部分可以隐藏在宏后面,这就是我在
Hedley中所做的:
#if \
HEDLEY_GNUC_HAS_ATTRIBUTE(pure,2,96,0) || \
HEDLEY_INTEL_VERSION_CHECK(16,0,0) || \
HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
HEDLEY_TI_VERSION_CHECK(8,0,0) || \
(HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
HEDLEY_PGI_VERSION_CHECK(17,10,0)
# define HEDLEY_PURE __attribute__((__pure__))
#elif HEDLEY_TI_VERSION_CHECK(6,0,0) && defined(__cplusplus)
# define HEDLEY_NO_RETURN _Pragma("FUNC_IS_PURE;")
#else
# define HEDLEY_PURE
#endif
#if HEDLEY_GNUC_HAS_ATTRIBUTE(const, 2, 5, 0) || \
HEDLEY_INTEL_VERSION_CHECK(16,0,0) || \
HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
HEDLEY_TI_VERSION_CHECK(8,0,0) || \
(HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
HEDLEY_PGI_VERSION_CHECK(17,10,0)
# define HEDLEY_CONST __attribute__((__const__))
#else
# define HEDLEY_CONST HEDLEY_PURE
#endif
这不包括需要函数名称作为参数的变体,但它仍然涵盖了绝大多数用户,并且在任何地方都可以安全使用。
如果您不想使用 Hedley(它是一个公共域/CC0 标头),替换内部版本宏应该不会太难。如果您选择这样做,您可能应该将您的端口基于 Hedley repo 而不是这个答案,因为我更有可能使其保持最新。