Completing string and string_view concatenation

3,784 views
Skip to first unread message

johe...@gmail.com

unread,
Nov 26, 2016, 10:14:16 PM11/26/16
to ISO C++ Standard - Future Proposals
Currently, the following, reasonable expressions are ill-formed

"string"s  + "_view"sv
"string"sv + "_view"s


even though you can use std::string's operator+= and append member functions if the rhs is a std::string_view.

I would like to propose the introduction of the std::string::operator+ overloads that would make such expressions well-formed. This would make the interface consistent, and prevent having to do less intuitive work-arounds to get equivalent effects:

auto sv {"C++17"sv};
auto str1 {std::string{sv} + " today"s}; // explicit conversion
auto str2 {"Today: "s += sv}; // why not +?
auto str3 {("Today: "s += sv) + ", tomorrow: "s += sv}; // messy


I had submitted a LWG issue on this. Here, I quote part of the reply by Daniel Krügler.

The second point is whether this is actually a feature request, not a
library defect. The design of basic_string_view intentionally did
support comparison, but not concatenations. This is obviously
evolution material, so I would strongly recommend to write a proposal
for this.

I tried hunting down why there's no operator+, and only found this in N3512:

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.

I can't believe that would be the only reason.

Here's the proposed wording included in my non-accepted issue.

Proposed wording:

This wording is relative to N4606.

Modify [string.classes]:

    ...
    template<class charT, class traits, class Allocator>
      basic_string<charT, traits, Allocator>
        operator+(basic_string<charT, traits, Allocator>&& lhs,
                  basic_string<charT, traits, Allocator>&& rhs);
    template<class charT, class traits, class Allocator>
      basic_string<charT, traits, Allocator>
        operator+(basic_string_view<charT, traits> lhs,
                  const basic_string<charT, traits, Allocator>& rhs);
    template<class charT, class traits, class Allocator>
      basic_string<charT, traits, Allocator>
        operator+(basic_string_view<charT, traits> lhs,
                  basic_string<charT, traits, Allocator>&& rhs);

    template<class charT, class traits, class Allocator>
      basic_string<charT, traits, Allocator>
        operator+(const charT* lhs,
                  const basic_string<charT, traits, Allocator>& rhs);
    ...
    template<class charT, class traits, class Allocator>
      basic_string<charT, traits, Allocator>
        operator+(charT lhs, basic_string<charT, traits, Allocator>&& rhs);
    template<class charT, class traits, class Allocator>
      basic_string<charT, traits, Allocator>
        operator+(const basic_string<charT, traits, Allocator>& lhs,
                  basic_string_view<charT, traits> rhs);
    template<class charT, class traits, class Allocator>
      basic_string<charT, traits, Allocator>
        operator+(basic_string<charT, traits, Allocator>&& lhs,
                  basic_string_view<charT, traits> rhs);

    template<class charT, class traits, class Allocator>
      basic_string<charT, traits, Allocator>
        operator+(const basic_string<charT, traits, Allocator>& lhs,
                  const charT* rhs);
    ...

Add after [string::op+]/4:

    template<class charT, class traits, class Allocator>
      basic_string<charT, traits, Allocator>
        operator+(basic_string_view<charT, traits> lhs,
                  const basic_string<charT, traits, Allocator>& rhs);

    Returns: basic_string<charT, traits, Allocator>(lhs) + rhs.

    template<class charT, class traits, class Allocator>
      basic_string<charT, traits, Allocator>
        operator+(basic_string_view<charT, traits> lhs,
                  basic_string<charT, traits, Allocator>&& rhs);

    Returns: std::move(rhs.insert(0, lhs)).

Add after [string::op+]/10:

    template<class charT, class traits, class Allocator>
      basic_string<charT, traits, Allocator>
        operator+(const basic_string<charT, traits, Allocator>& lhs,
                  basic_string_view<charT, traits> rhs);

    Returns: lhs + basic_string<charT, traits, Allocator>(rhs).

    template<class charT, class traits, class Allocator>
      basic_string<charT, traits, Allocator>
        operator+(basic_string<charT, traits, Allocator>&& lhs,
                  basic_string_view<charT, traits> rhs);

    Returns: std::move(lhs.insert(rhs)).

janis....@gmail.com

unread,
Apr 10, 2017, 3:57:38 AM4/10/17
to ISO C++ Standard - Future Proposals, johe...@gmail.com
I agree with your proposal. I was surprised when it wasn't possible to operator+ string_view - feels like inconsistent interface.

olafv...@gmail.com

unread,
Apr 13, 2017, 4:24:26 AM4/13/17
to ISO C++ Standard - Future Proposals, johe...@gmail.com
Op zondag 27 november 2016 04:14:16 UTC+1 schreef johe...@gmail.com:
I can't believe that would be the only reason.

Why not?

I'd love to have those operators too but in the meantime you can easily define them yourself:

Reply all
Reply to author
Forward
0 new messages