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.