Skip to content

Instantly share code, notes, and snippets.

@kaidokert
Last active January 6, 2020 04:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kaidokert/1cca80f4648631422c5891e5c31e7ac8 to your computer and use it in GitHub Desktop.
Save kaidokert/1cca80f4648631422c5891e5c31e7ac8 to your computer and use it in GitHub Desktop.
C++11 const string length, gcc 4.7+ and clang 3.5+
// https://godbolt.org/z/uu4TMP
// API: constexpr size_t const_strlen( "foo" );
// Much more readable version here: https://gist.github.com/kaidokert/dfc08be8e75a3fc650d3daf8e89c3fe9
// but that doesn't work with GCC before version 7
#include <utility> //std::forward
#include <cstddef> //std::size_t
namespace detail {
template<size_t COUNTER, typename T>
struct recursive_array {};
template<size_t COUNTER, size_t N> // General case, Counter=0...N-1
struct recursive_array<COUNTER, const char (&)[N]> {
constexpr static size_t check(const char(&x)[N]) {
return x[COUNTER] == '\0' ? COUNTER :
recursive_array<COUNTER + 1, const char(&)[N]>::check(x);
}
};
template<size_t N> // Termination case, COUNTER = N
struct recursive_array<N, const char (&)[N]> {
constexpr static size_t check(const char(&)[N]) {
return N;
}
};
template<typename T>
struct len_helper {
constexpr static size_t len(const char *x) {
return *x == '\0' ? 0 : 1 + len(x + 1);
}
};
template<>
struct len_helper<std::nullptr_t> {
constexpr static size_t len(std::nullptr_t) {
return 0;
}
};
template<size_t N>
struct len_helper<const char (&)[N]> {
constexpr static size_t len(const char (&x)[N]) {
return recursive_array<0, const char (&)[N]>::check(x);
}
};
} // namespace detail
template<typename T>
constexpr size_t const_strlen(T&& x) {
return detail::len_helper< T >::len(std::forward< T >(x) );
}
int main() {
constexpr const char ce_const_arr_empty[] = "";
constexpr const char ce_const_arr[] = "foo";
constexpr char ce_arr[] = "foo";
constexpr const char * ptr = "foo";
constexpr const char real_long[] =
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum sit amet erat accumsan, "
"pellentesque libero id, pulvinar diam. Cras ullamcorper velit vitae tortor ultricies, at semper mi consequat. "
"Vestibulum pretium aliquam sapien, sit amet"
#if !(__clang_major__ < 4)
" placerat libero. Fusce in tempus risus. Lorem ipsum dolor sit amet, "
"consectetur adipiscing elit. Aenean lobortis, ante maximus tempor ullamcorper, tortor sem iaculis purus, dignissim "
"consectetur massa leo a mauris. Aliquam aliquam bibendum eros eget viverra."
#endif
;
SASSERT_EQ( const_stringlen(nullptr), 0);
SASSERT_EQ( const_stringlen(""), 0);
SASSERT_EQ( const_stringlen("\0" "bar"), 0);
SASSERT_EQ( const_stringlen("f\0" "ba"), 1);
SASSERT_EQ( const_stringlen("fo\0" "b"), 2);
SASSERT_EQ( const_stringlen((const char*)"\0" "bar"), 0);
SASSERT_EQ( const_stringlen(ce_const_arr_empty) ,0);
SASSERT_EQ( const_stringlen(ptr) ,3);
SASSERT_EQ( const_stringlen(ce_const_arr) ,3);
SASSERT_EQ( const_stringlen(ce_arr) ,3);
#if (__clang_major__ < 4) //old clang defaults to 256 recursion depth
SASSERT_EQ( const_stringlen(real_long) ,245);
#else //gcc defaults to 512
SASSERT_EQ( const_stringlen(real_long) ,504);
#endif
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment