diff --git a/README.md b/README.md index b5b7060..ed0ef39 100644 --- a/README.md +++ b/README.md @@ -201,7 +201,16 @@ Define this to 1 to provide `std::string`– `nonstd::string_view` interoper At default, *string-view lite* provides operations to overload the `operator<<`. If you want to use the library without the use of standard streams, you can control this with the following macro: -Dnssv_CONFIG_NO_STREAM_INSERTION=1 -Define this to 1 to omit the use of standard streams. Default is undefined +Define this to 1 to omit the use of standard streams. Default is undefined. + +### Avoid `constexpr` with `std::search()` + +At default, *string-view lite* may use constexpr with `std::search()` for `string_view::find()` when compiling for C++11 or C++14, whereas `std::search()` is only constexpr since C++20. This may occur when macro `__OPTIMIZE__` is not defined and a non-recursive implementation for search is selected. Macro `__OPTIMIZE__` is used with GCC and clang. + +If you encounter an error related to this, you can control this behaviour with the following macro: + +-Dnssv_CONFIG_CONSTEXPR11_STD_SEARCH=0 +Define this to 0 to omit the use constexpr with `std::search()` and substitute a local implementation using `nssv_constexpr14`. Default is 1. ### Enable compilation errors diff --git a/include/nonstd/string_view.hpp b/include/nonstd/string_view.hpp index f486b45..84a565f 100644 --- a/include/nonstd/string_view.hpp +++ b/include/nonstd/string_view.hpp @@ -69,6 +69,10 @@ # define nssv_CONFIG_NO_STREAM_INSERTION 0 #endif +#ifndef nssv_CONFIG_CONSTEXPR11_STD_SEARCH +# define nssv_CONFIG_CONSTEXPR11_STD_SEARCH 1 +#endif + // Control presence of exception handling (try and auto discover): #ifndef nssv_CONFIG_NO_EXCEPTIONS @@ -567,12 +571,31 @@ constexpr const CharT* search( basic_string_view haystack, basic_ // non-recursive: +#if nssv_CONFIG_CONSTEXPR11_STD_SEARCH + template< class CharT, class Traits = std::char_traits > constexpr const CharT* search( basic_string_view haystack, basic_string_view needle ) { return std::search( haystack.begin(), haystack.end(), needle.begin(), needle.end() ); } +#else // nssv_CONFIG_CONSTEXPR11_STD_SEARCH + +template< class CharT, class Traits = std::char_traits > +nssv_constexpr14 const CharT* search( basic_string_view haystack, basic_string_view needle ) +{ + while ( needle.size() <= haystack.size() ) + { + if ( haystack.starts_with(needle) ) + { + return haystack.cbegin(); + } + haystack = basic_string_view{ haystack.begin() + 1, haystack.size() - 1U }; + } + return haystack.cend(); +} +#endif // nssv_CONFIG_CONSTEXPR11_STD_SEARCH + #endif // OPTIMIZE #endif // nssv_CPP11_OR_GREATER && ! nssv_CPP17_OR_GREATER