Alb*_*ert 32 c++ gcc const function-attributes
pure是一个函数属性,表示函数不会修改任何全局内存.
const是一个函数属性,表示函数不读取/修改任何全局内存.
鉴于该信息,编译器可以进行一些额外的优化.
GCC示例:
float sigmoid(float x) __attribute__ ((const));
float calculate(float x, unsigned int C) {
float sum = 0;
for(unsigned int i = 0; i < C; ++i)
sum += sigmoid(x);
return sum;
}
float sigmoid(float x) { return 1.0f / (1.0f - exp(-x)); }
Run Code Online (Sandbox Code Playgroud)
在该示例中,编译器可以将函数计算优化为:
float calculate(float x, unsigned int C) {
float sum = 0;
float temp = C ? sigmoid(x) : 0.0f;
for(unsigned int i = 0; i < C; ++i)
sum += temp;
return sum;
}
Run Code Online (Sandbox Code Playgroud)
或者如果您的编译器足够聪明(并且对浮点数不那么严格):
float calculate(float x, unsigned int C) { return C ? sigmoid(x) * C : 0.0f; }
Run Code Online (Sandbox Code Playgroud)
如何为不同的编译器(即GCC,Clang,ICC,MSVC或其他编译器)标记功能?
Alb*_*ert 28
通常,似乎几乎所有编译器都支持GCC属性.到目前为止,MSVC是唯一不支持它们的编译器(也没有任何替代方案).
First, it's useful to note that "const" is a more strict version of "pure", so "pure" can be used as a fallback if a compiler doesn't implement "const".
As others have mentioned, MSVC doesn't really have anything similar,
but a lot of compilers have adopted the GCC syntax, including many
which don't define __GNUC__
(and some which sometimes do and
sometimes don't, depending on flags).
__has_attribute(pure)
and
__has_attribute(const)
to detect them, but it's probably fine to
just rely on clang setting __GNUC__
. This also includes compilers
based on clang like emscripten and XL C/C++ 13+.__TI_GNU_ATTRIBUTE_SUPPORT__
) supports both.Of these, clang always defines __GNUC__
and friends (currently to
4.2, IIRC). Intel defines __GNUC__
by default (though it can be
suppressed with -no-gcc) as does PGI in C++ mode (but not in C
mode). The others you'll have to check for manually.
Oracle Developer Studio has also supported pragmas since it was known as Forte Developer 6. They're used a bit differently since they require you to specify the function name:
/* pure: */
#pragma does_not_write_global_data (funcname)
/* const; SPARC-only until 12.2 */
#pragma no_side_effect (funcname)
Run Code Online (Sandbox Code Playgroud)
TI 6.0+ (at least) supports a #pragma FUNC_IS_PURE;
pragma in C++
mode only. In C mode, it's #pragma FUNC_IS_PURE(funcname);
.
Most of this can be hidden behind a macro, which is what I've done in 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
Run Code Online (Sandbox Code Playgroud)
This doesn't include the variants which would require the function names as an argument, but it still covers the vast majority of users, and it's safe to use everywhere.
If you don't want to use Hedley (it's a single public domain / CC0 header) it shouldn't be too difficult to replace the internal version macros. If you choose to do that, you should probably base your port on the Hedley repo instead of this answer as I'm much more likely to keep it up to date.
归档时间: |
|
查看次数: |
8710 次 |
最近记录: |