0

I am trying to create a very simple function:

bool is_palidrome(const std::string& s)
{
    std::string r(s.crbegin(), s.crend());
    return s==r;
}

In order to avoid unnecessary allocations I thought I could use a string_view:

bool is_palidrome(const std::string& s)
{
   std::string_view r(s.crbegin(), s.crend());
   return s==r;
}

However the last function fails to compile since the compiler cannot find a suitable constructor (I tried both g++ 12.2 and clang++ 15.0). Why there isn't a constructor for this case while std::string_view r(s.cbegin(), s.cend()); works perfectly? I check the standard https://en.cppreference.com/w/cpp/string/basic_string_view/basic_string_view but I do not see which condition is not satisfied.

apelle
  • 144
  • 1
  • 9
  • 6
    A string_view is only ever over an existing contiguous buffer. How is it supposed to work? – StoryTeller - Unslander Monica Oct 06 '22 at 16:12
  • Mine is probably a stupid comment but if [a,b] is continuous isn't [b,a] as well? – apelle Oct 06 '22 at 16:15
  • 1
    One of the most common ways to check for a palindrome is to use a simple loop, indexing from both the beginning and the end, and compare individual characters until the indexes passes each other. It's actually going to be more effective than a comparison, because in a worst case (it's a palindrome) the comparison using `==` will compare the *whole* string, while a loop as described above will only compare *half* the string. – Some programmer dude Oct 06 '22 at 16:17
  • 1
    Regarding the [b,a] thing, that's not how computers work. The buffer needs to be contiguous in *one direction* (forward from a to b). You can't go backwards in space like that. – Some programmer dude Oct 06 '22 at 16:19
  • the full error message and command line will probably help to shed some light, it could be that there is no constructor to create a string from a string_view required by operator== – Alessandro Teruzzi Oct 06 '22 at 16:19
  • @Someprogrammerdude Thank you very much you gave me a good hint. The palindrome function was just a minimal working example to explain my problem. – apelle Oct 06 '22 at 16:25
  • 3
    This is an [XY Problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). You can implement `is_palandrome` without allocating. "Using `std::string_view` with reverse iterators" is not the solution, however. – Drew Dormann Oct 06 '22 at 16:25
  • @DrewDormann No it isn't in my code I truly need to reverse a string and I thought a nice and fast to write option was with std::string_view – apelle Oct 06 '22 at 16:29
  • 1
    @Someprogrammerdude -- well, it will actually compare the whole string, but using only `Length / 2` iterations comparing 2-characters per-iteration `:)` – David C. Rankin Oct 06 '22 at 16:58

2 Answers2

3

First it is better to have argument as std::string_view (so literals and std::string are covered without any extra allocations).

Then you need to check only half of the range and use algoritm std::equal (as in other answer).

bool is_palidrome(std::string_view s)
{
    return std::equal(begin(s), begin(s) + size(s) / 2, rbegin(s));
}

Note ADL allows to skip some std::.

Marek R
  • 32,568
  • 6
  • 55
  • 140
2

You don't need std::string_view to do this.

To implement your approach - comparing the entire string with its reverse - you can use std::equal.

bool is_palindrome(const std::string& s)
{
    return std::equal( begin(s), end(s), rbegin(s) );
}
Drew Dormann
  • 59,987
  • 13
  • 123
  • 180
  • 1
    Note this code is comparing the *entire* string, when really you only need to compare *half* of the string – Remy Lebeau Oct 06 '22 at 16:42
  • @RemyLebeau absolutely correct. Marek R's answer changes what OP was attempting, and makes the function better in two ways. – Drew Dormann Oct 06 '22 at 16:45