Constexpr非常适合编译优化。例如......
strlen(char*)
可以使用....预编译。
constexpr inline size_t strlen_constexpr(char* baseChar) {
return (
( baseChar[0] == 0 )
?(// if {
0
)// }
:(// else {
strlen_constexpr( baseChar+1 ) + 1
)// }
);
}
在优化时,它给运行成本“0” ...但在运行时速度超过10 + x
// Test results ran on a 2010 macbook air
--------- strlen ---------
Time took for 100,000 runs:1054us.
Avg Time took for 1 run: 0.01054us.
--------- strlen_constexpr ---------
Time took for 100,000 runs:19098us.
Avg Time took for 1 run: 0.19098us.
是否存在可以使用单个统一功能的现有宏/模板黑客攻击。即
constexpr size_t strlen_smart(char* baseChar) {
#if constexpr
... constexpr function
#else its runtime
... runtime function
}
或者某些超载黑客会允许以下
constexpr size_t strlen_smart(char* baseChar) {
... constexpr function
}
inline size_t strlen_smart(char* baseChar) {
... runtime function
}
注意:此问题适用于一般概念。有两个单独的函数用于运行时和constexpr而不是给定的示例函数。
免责声明:将编译器设置为-O3(优化级别)足以修复99.9%的静态字符串优化,使上面的所有示例“毫无意义”。但这不是问题的重点,因为它适用于其他“例子”,而不仅仅是strlen
。
答案 0 :(得分:10)
我不知道任何通用的方法,但我知道有两种可能的特定情况。
gcc和clang复制了gcc的所有功能,还有一个内置函数__builtin_constant_p
。我不确定gcc是否会正确地将内联函数的参数视为常量,但我担心你必须从宏中使用它:
#define strlen_smart(s) \
(__builtin_constant_p(s) && __builtin_constant_p(*s) ? \
strlen_constexpr(s) : \
strlen(s))
可能有用。请注意,我正在为constexpr测试s
和*s
,因为指向静态缓冲区的指针是编译时常量,而它的长度是而不是。
对于strlen
的特定强制转换,您可以使用以下事实:字符串文字不类型为const char *
,但类型为const char[N]
,隐式转换为{ {1}}。但它也会转换为const char *
,而const char (&)[N]
则不会。
所以你可以定义:
const char *
(明显template <size_t N>
constexpr size_t strlen_smart(const char (&array)[N])
strlen_smart
转发const char *
}
我有时使用这种类型的参数的函数,即使在C ++ 98中定义对应(我没有尝试重载strlen
本身,但重载是这样我可以避免调用它) :
strlen
这有问题
template <size_t N>
size_t strlen_smart(const char (&)[N]) { return N - 1; }
应该说0,但是那个优化的变体只是说9.这些函数在这样的缓冲区上调用是没有意义的,所以我不在乎。