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
.
Constant expression, constexpr , code in C++ aims to move non-changing repetitive computations at runtime to compile time. For example, you can write a function that calculates π² at compile time, so, whenever you run the program, π² value is already there. constexpr functions are also allowed to be called at runtime.
Yes. I believe putting such const ness is always a good practice wherever you can. For example in your class if a given method is not modifying any member then you always tend to put a const keyword in the end.
Understanding constexpr Specifier in C++ constexpr is a feature added in C++ 11. The main idea is a performance improvement of programs by doing computations at compile time rather than run time.
constexpr functions will be evaluated at compile time when all its arguments are constant expressions and the result is used in a constant expression as well.
I don't know any generic way, but I know two specific cases where it is possible.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With