131

Since C++17, we have std::string_view, a light-weight view into a contiguous sequence of characters that avoids unnecessary copying of data. Instead of having a const std::string& parameter, it is now often recommended to use std::string_view.

However, one quickly finds out that switching from const std::string& to std::string_view breaks code that uses string concatenation as there is no support for concatenating std::string and std::string_view:

std::string{"abc"} + std::string_view{"def"}; // ill-formed (fails to compile)
std::string_view{"abc"} + std::string{"def"}; // ill-formed (fails to compile)

Why is there no support for concatenating std::string and std::string_view in the standard?

vitaut
  • 49,672
  • 25
  • 199
  • 336
s3rvac
  • 9,301
  • 9
  • 46
  • 74
  • 15
    Most likely an oversight. That said, it doesn't take much to add a `operator +` to make the code work. – NathanOliver Jun 19 '17 at 17:29
  • 9
    Just found this: https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/1RcShRhrmRc – NathanOliver Jun 19 '17 at 17:38
  • 3
    What I also miss is a member function of std::basic_string that returns the std::basic_string_view of a sub-string (similar to the "substr" member function), perhaps named "substr_view". – CAF Jun 19 '17 at 18:06
  • 1
    have a look at this. https://github.com/OlafvdSpek/xbt/blob/master/misc/xbt/string_view.h – asad_nitp Sep 27 '17 at 17:12
  • 1
    @NathanOliver Doing that would conflict with a possible future addition of this operator to the language, so it is not recommended. – MangaD Jan 19 '22 at 16:27
  • its also not possible to add two `std::string_view`s `error: no match for 'operator+' (operand types are 'std::string_view' {aka 'std::basic_string_view'} and 'std::string_view' {aka 'std::basic_string_view'})` – simplename Aug 24 '22 at 07:06

2 Answers2

81

The reason for this is given in n3512 string_ref: a non-owning reference to a string, revision 2 by Jeffrey Yasskin:

I also omitted operator+(basic_string, basic_string_ref) because LLVM returns a lightweight object from this overload and only performs the concatenation lazily. If we define this overload, we'll have a hard time introducing that lightweight concatenation later.

It has been later suggested on the std-proposals mailing list to add these operator overloads to the standard.

vitaut
  • 49,672
  • 25
  • 199
  • 336
  • 135
    Wow. Just wow! This seems to be the *worst* possible reason for leaving something out. The standard is supposed to be for the good of the *language,* not for any particular implementation. I'm also wary of the "performs the concatenation lazily" - does this mean that, should we have a memory shortage, the exception for adding to the original string will *also* be deferred? I sure as hell hope not, I want to know if an operation fails when *I* do it, not ten minutes later when I access the result. – paxdiablo Dec 10 '17 at 03:57
  • 4
    Hopefully someone submit's a proposal to include these operators. – vitaut Dec 10 '17 at 04:00
  • 5
    In the [fmtlib/fmt](https://github.com/fmtlib/fmt) library works great with `string_view`. – void.pointer Aug 19 '19 at 20:45
  • 14
    [`std::basic_string::append()`](https://en.cppreference.com/w/cpp/string/basic_string/append) has an overload that accepts everything that can be implicitly converted to a `std::string_view`. Of course this is not the same as `operator+()`. – Brandlingo Dec 09 '19 at 15:06
  • 2
    What alternatives do the commentators here do suggest if one needs an efficient c++ string concatenation(i.e. string builder)? For example, c# libraries has an efficient uri_builder class, which takes a group of strings and creates one by using a to_string() method; which in affect could be realized if string_view were to have a +() overload. – b.g. Jul 01 '20 at 08:37
  • 1
    my_s.insert(0, my_sv); // s = sv + s my_s.append(my_sv); // s = s + sv – vSzemkel Dec 31 '20 at 13:58
  • @b.g.: There's [a question](https://stackoverflow.com/questions/2462951/c-equivalent-of-stringbuffer-stringbuilder) for that. – Jacob Manaker Nov 18 '21 at 06:06
  • As a workaround, you can also call `string_object + string_view_object.data()`. This actually calls the `operator+()` overload that takes a `const char*`, but that works and should be efficient – joesdiner Jan 05 '22 at 21:21
  • 5
    @joesdiner That is NOT safe, `data` is not null-terminated and `const char*`-taking overload expects it to be. – Quimby Feb 02 '22 at 17:00
  • is there an official proposal for this yet? – Poeta Kodu Mar 19 '22 at 22:36
  • This is _especially_ glaring when compared to [std::basic_string::operator+=()](https://en.cppreference.com/w/cpp/string/basic_string/operator%2B%3D), which has taken `string_view`-likes of all sorts since `basic_string_view` was introduced. The cleanest equivalent to adding `string_view sv`s to `string s`s is literally `s + ""s.operator+=(sv)`, and I'm not even sure how safe that is. – Justin Time - Reinstate Monica Sep 02 '23 at 18:45
  • (In the sense of actually performing concatenation between `string` and `string_view` specifically. Strictly speaking, creating a string from `sv`, so you could add `s + std::string(sv)`, is cleaner and more performant, but that concatenates two strings. `""s.operator+=(sv)` does string concatenation, too, but it _does_ at least concatenate `sv` to a temporary string in the process. This is mainly an illustrative point to highlight the issue, not actual code I'd expect to see somewhere.) – Justin Time - Reinstate Monica Sep 02 '23 at 18:55
24

I've submitted P2591: Concatenation of strings and string views, linking to this SO question. The paper at this point is targeted at C++26 minimum.

peppe
  • 21,934
  • 4
  • 55
  • 70
  • 2
    This probably isn't where critique of the proposal should go, but I noticed that your example code has `view` as an `std::string`, not as an `std::string_view`. – Hasturkun Jun 02 '22 at 09:50
  • 1
    Hi! Yes, duly noted; I've already fixed that and another couple of typos in an upcoming revision. – peppe Jun 02 '22 at 16:47
  • Will P2591 allow all of these? 1: sv + sv 2: sv + std::string 3: sv + string literal (const char*) 4: sv + character literal (char) – PFee Jun 09 '22 at 14:11
  • No, that's out of scope (in scope for a string builder, perhaps). Just kickstart the chain with a conversion to `string`, then keep chaining. (IOW, those opreations need to allocate memory; hence you need an allocator; but none of those operations let you specify one) – peppe Jun 10 '22 at 17:09
  • 9
    C++26?... Mind blown. IMHO this should be considered a defect and applied retroactively to C++17. – Super-intelligent Shade Sep 11 '22 at 03:44