string-view-lite
string-view-lite copied to clipboard
std::search called in search() when compiling with C++14
I'm trying to compile one of the examples of my cuda-api-wrappers library, which uses string-view-lite, using C++14 instead of C++11 like I was compiling it so far. I get:
... snip ...
/home/eyalroz/src/mine/cuda-api-wrappers/examples/other/jitify/string_view.hpp:572:23: error: call to non-‘constexpr’ function ‘_FIter1 std::search(_FIter1, _FIter1, _FIter2, _FIter2) [with _FIter1 = const char*; _FIter2 = const char*]’
572 | return std::search( haystack.begin(), haystack.end(), needle.begin(), needle.end() );
| ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
... snip...
and, indead, std::search is not constexpr before C++20.
Oh, actually, maybe it's a dupe of my other bug.
You can try defining __OPTIMIZE__ before including string_view.hpp or build with optimizations enabled.
https://github.com/martinmoene/string-view-lite/blob/5b1d95fe2c0ee18e654876487898b9a423a954db/include/nonstd/string_view.hpp#L554-L576
https://stackoverflow.com/questions/14618249/is-there-a-builtin-macro-defined-when-optimisation-is-enabled-in-clang
@eyalroz, @oliverlee
The unconditional constexpr in the non-optimize case of constexpr const CharT* search() should perhaps be replaced with something like nssv_constexpr20_lib.
I'd like nssv_HAVE_CONSTEXPR_20_LIB to be not overly restrictive as it may be as show below. Suggestions are quite welcome.
// Presence of C++20 library features:
#define nssv_HAVE_CONSTEXPR_20_LIB nssv_CPP20_000
// ...
#if nssv_HAVE_CONSTEXPR_20_LIB
# define nssv_constexpr20_lib constexpr
#else
# define nssv_constexpr20_lib /*constexpr*/
#endif
// ...
#else // OPTIMIZE
// non-recursive:
template< class CharT, class Traits = std::char_traits<CharT> >
nssv_constexpr20_lib const CharT* search( basic_string_view<CharT, Traits> haystack, basic_string_view<CharT, Traits> needle )
{
return std::search( haystack.begin(), haystack.end(), needle.begin(), needle.end() );
}
#endif // OPTIMIZE
I think it makes sense to remove the branch on _OPTIMIZE_. By removing the call to std::search, this would allow use in constant expressions with debug builds.
However, a possibly recursive search, possibly exhausting the stack doesn't look like the right thing to do at default.
Ah right. In that case, what about replacing the second implementation with something like:
template< class CharT, class Traits = std::char_traits<CharT> >
nssv_constexpr14 const CharT* search( basic_string_view<CharT, Traits> haystack, basic_string_view<CharT, Traits> needle )
{
while (needle.size() <= haystack.size()) {
if (haystack.starts_with(needle)) {
return haystack.cbegin();
}
haystack = basic_string_view<CharT, Traits>{ haystack.begin() + 1, haystack.size() - 1U };
}
return haystack.cend();
}
Although I suppose it would make sense to allow a user to select std::search via a preprocessor macro (or vice-versa).
@oliverlee Thanks for your suggestions!
Thanks for sharing your implementation of string view!