如何有“constexpr和运行时”别名 [英] How to have "constexpr and runtime" alias

查看:175
本文介绍了如何有“constexpr和运行时”别名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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慢

  //测试结果运行在2010 macbook空气
--------- strlen ---------
100,000次运行所需的时间:1054us。
平均运行时间:0.01054us。
--------- strlen_constexpr ---------
100,000次运行所花费的时间:19098us。
平均运行时间:0.19098us。

是否有任何现有的宏/模板黑客可以使用单个统一的函数。即

  constexpr size_t strlen_smart(char * baseChar){
#if constexpr
... constexpr函数
#else其运行时
...运行时函数
}

$

  constexpr size_t strlen_smart(char * baseChar){
.. 。constexpr function
}

inline size_t strlen_smart(char * baseChar){
...运行时函数
}

注意:此问题适用于一般概念。

免责声明:将编译器设置为-O3(优化级别)足以修复99.9%的静态字符优化,使所有上面的例子无意义。但这不是问题的重点,因为它适用于其他示例,而不只是 strlen

解决方案

我不知道任何通用的方法,但我知道两个具体的情况下是可能的。



编译器



同样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 ,因为指向静态缓冲区



Bonus:文字的具体情况(不是真正的答案)



对于 strlen 的特定转换,您可以使用字符串字面值不是类型 const char * 但类型 const char [N] 隐式转换为 const char * / code>。但它也转换为 const char(&)[N] 以及 const char * / p>

所以你可以定义:

  template< size_t N> 
constexpr size_t strlen_smart(const char(& array)[N])

显然 strlen_smart const char * 转发到 strlen



我有时使用这种类型的参数的函数,即使在C ++ 98中,定义对应(我没有尝试重载 strlen 本身,但重载是所以我可以避免调用它):

  template< size_t N> ; 
size_t strlen_smart(const char(&)[N]){return N - 1; }

这有一个问题,

  char buffer [10] = {0}; 

strlen_smart(buffer);

应该是0,但是优化的变体只是说9.这些函数没有意义调用像这样的缓冲区,所以我不在乎。


Constexpr can be awsome and useful for compilation optimisation. For example...

strlen(char*)

Can be precompiled using....

constexpr inline size_t strlen_constexpr(char* baseChar) {
    return (
            ( baseChar[0] == 0 )
            ?(// if {
              0
              )// }
            :(// else {
              strlen_constexpr( baseChar+1 ) + 1 
              )// }
            );
}

Which gives it a runtime cost of "0" when optimised... But is more than 10+x slower on runtime

// 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.

Are there any existing macro / template hack where a single unified function can be used instead. ie.

constexpr size_t strlen_smart(char* baseChar) {
    #if constexpr
    ... constexpr function
    #else its runtime
    ... runtime function
}

Or some overloading hack that would allow the following

constexpr size_t strlen_smart(char* baseChar) {
    ... constexpr function
}

inline size_t strlen_smart(char* baseChar) {
    ... runtime function
}

Note: This question applies to the concept in general. Of having 2 separate functions for runtime and constexpr instead of the example functions given.

Disclaimer: Setting the compiler to -O3 (optimization level) is more than enough to fix 99.9% of static char optimizations making all the examples above "pointless". But that's beside the point of this question, as it applies to other "examples", and not just strlen.

解决方案

I don't know any generic way, but I know two specific cases where it is possible.

Specific case of some compilers

Also gcc, and clang which copies all features of gcc, have a built-in function __builtin_constant_p. I am not sure whether gcc will correctly see argument to inline function as constant, but I fear you'd have to use it from a macro:

#define strlen_smart(s) \
    (__builtin_constant_p(s) && __builtin_constant_p(*s) ? \
        strlen_constexpr(s) : \
        strlen(s))

Might be of use. Note that I am testing both s and *s for constexpr, because pointer to static buffer is a compile time constant while it's length is not.

Bonus: Specific case of literals (not an actual answer)

For the specific cast of strlen you can use the fact that string literals are not of type const char * but of type const char[N] that implicitly converts to const char *. But it also converts to const char (&)[N] as well while const char * does not.

So you can define:

template <size_t N>
constexpr size_t strlen_smart(const char (&array)[N])

(plus obviously strlen_smart on const char * forwards to strlen)

I've sometimes used function with this type of argument even in C++98 with definition corresponding to (I didn't try to overload strlen itself, but the overloads were so I could avoid calling it):

template <size_t N>
size_t strlen_smart(const char (&)[N]) { return N - 1; }

This has the problem that for

char buffer[10] = { 0 };

strlen_smart(buffer);

should say 0, but that optimized variant just says 9. The functions don't make sense to be called on buffers like that so I didn't care.

这篇关于如何有“constexpr和运行时”别名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆