string-view-lite icon indicating copy to clipboard operation
string-view-lite copied to clipboard

std::search called in search() when compiling with C++14

Open eyalroz opened this issue 3 years ago • 9 comments

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.

eyalroz avatar May 27 '22 21:05 eyalroz

Oh, actually, maybe it's a dupe of my other bug.

eyalroz avatar May 27 '22 21:05 eyalroz

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

oliverlee avatar Dec 28 '23 04:12 oliverlee

@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

martinmoene avatar Dec 28 '23 13:12 martinmoene

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.

oliverlee avatar Dec 28 '23 14:12 oliverlee

However, a possibly recursive search, possibly exhausting the stack doesn't look like the right thing to do at default.

martinmoene avatar Dec 28 '23 16:12 martinmoene

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();
}

oliverlee avatar Dec 28 '23 19:12 oliverlee

Although I suppose it would make sense to allow a user to select std::search via a preprocessor macro (or vice-versa).

oliverlee avatar Dec 28 '23 19:12 oliverlee

@oliverlee Thanks for your suggestions!

martinmoene avatar Dec 28 '23 22:12 martinmoene

Thanks for sharing your implementation of string view!

oliverlee avatar Dec 28 '23 23:12 oliverlee