0

Which is the correct/safer/efficient way to concatenate strings with a string_view object to produce a string:

std::string_view foo{"foo"};
auto concat = foo.data() + std::to_string(45);
OR
auto concat = std::string(foo) + std::to_string(45);

Not using .data() results in a compilation error:

no match for ‘operator+’ (operand types are ‘std::string_view’ {aka ‘std::basic_string_view’} and ‘std::string’ {aka ‘std::__cxx11::basic_string’})
   18 |     auto concat = foo + std::to_string(45);
      |                   ~~~ ^ ~~~~~~~~~~~~~~~~~~
      |                   |                   |
      |                   |                   std::string {aka std::__cxx11::basic_string<char>}
      |                   std::string_view {aka std::basic_string_view<char>}

In the first usage that uses data(), I'm mainly concerned about this note from reference that says:

std::basic_string_view::data() returns a pointer to a buffer that is not necessarily null-terminated

But that call seems to work ok. So why would I prefer string constructed out of the string_view object method over passing the data pointer?

rookie
  • 1,168
  • 3
  • 14
  • 25
  • 2
    The short way is not available, there is [P2591R3](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2591r3.html), for C++26 maybe. – 273K Jul 08 '23 at 00:32
  • Could you comment on why choose data() over string constructing the string_view object? – rookie Jul 08 '23 at 00:37
  • As for the (not exact dupe), the only correct way is `std::string(foo) + std::to_string(45);` in ordinary cases. You particular case with `std::string_view foo{"foo"};` and `foo.data() + std::to_string(45);` is valid, because `foo` is built around the null-terminated data "foo". – 273K Jul 08 '23 at 00:40
  • Gotcha, thanks. So in this case the data() method is more efficient than string construction – rookie Jul 08 '23 at 00:46
  • Now I'm curious - when would a non-null terminated string view exist? AFAIK, the std::string_view foo{"foo"}; is how I'd create string_view objects – rookie Jul 08 '23 at 00:48
  • 1
    No. it may be less efficient. [operator+](https://en.cppreference.com/w/cpp/string/basic_string/operator%2B) needs to count the "foo" length for reserving space for the resulting string, whereas `foo` string view already knows the string length. – 273K Jul 08 '23 at 00:50
  • 3
    `char data[] = {'f', 'o', 'o'}; std::string_view foo{data, 3};` - `foo.data()` is not null-terminated. – 273K Jul 08 '23 at 00:52
  • About your comment about efficiency - I didn't quite follow that. My question was whether std::string(foo) was better than using foo.data() for concatenation. If `foo` knows the length already it should be more efficient, but you say otherwise. Could you clarify – rookie Jul 08 '23 at 01:01
  • 1
    @rookie: `std::string_view nulterminated{"foo"}; auto notnulterminated = nulterminated.substr(0, 1);` If you're *manipulating* `std::string_view` to get zero-copy string slicing, NUL-termination would be the exception, not the rule. It's only when the `std::string_view` is directly constructed from a string literal or `std::string` that you get the `NUL` termination (I believe `sv` terminated `string_view` literals have a NUL, but frankly, they probably shouldn't have, because it encourages your style of misuse). – ShadowRanger Jul 08 '23 at 01:08
  • So, std::string(nulterminated) is the better way to concatenate. When you say "your style of misuse" do you refer to using `data()` for concatenation? I really hoped this question wasn't closed because the duplicate does not have this specific discussion. – rookie Jul 08 '23 at 01:22
  • 1
    @rookie: "*the duplicate does not have this specific discussion*" It doesn't need to because any solution that involves "forget the entire point of the type and just get a `char const*` without any length information and create a `std::string` from it" is *always* a bad idea. – Nicol Bolas Jul 08 '23 at 02:21
  • 1
    @NicolBolas I'm not sure which method you're referring to when you say "forget the entire point of the type". Anyways, all of this could have been condensed in an answer and laid out for a novice such as myself. Instead there's bits and pieces in this comment thread (where I have still learned a lot). I'm sure you all understand how string_view works, but I don't and I came here looking for answers. The other question asks about how to create a string_view from string_view objects which is not what I asked. I'll leave this be. – rookie Jul 08 '23 at 04:18
  • 2
    @rookie: "*I'm not sure which method you're referring to when you say "forget the entire point of the type".*" I meant `.data()`, which loses the size information that is the *entire reason* to use `string_view` instead of just a `char const*`. – Nicol Bolas Jul 08 '23 at 04:21

0 Answers0