6

I am not 100% that the following code is semantically correct:

#include <iostream>
#include <experimental/string_view>

int main()
{
    std::string str = "lvalue string";

    std::experimental::string_view view_lvalue(str);
    std::experimental::string_view view_rvalue(std::string{"rvalue string"});

    std::cout << view_lvalue << '\n' << view_rvalue << '\n';
}

Live on Wandbox

Question: Can I legally bind a rvalue to std::experimental::basic_string_view, or is it just UB? If yes, how does it work? As far as I know, a rvalue does not bind to a const reference (which I assume the view holds to the original string) via the constructor, so I thought that at the end of the statement std::experimental::string_view view_rvalue(std::string{"rvalue string"}); the reference will be dangling. Does string_view use a more sophisticated approach?

I am asking this because I am trying to write a similar view for some matrix class, and don't yet know how to deal with rvalues (I can disable them of course, but I don't think it's the best approach).

vsoftco
  • 55,410
  • 12
  • 139
  • 252

1 Answers1

3

If cpprefernce is correct then this is UB. std::string_view has

A typical implementation holds only two members: a pointer to constant CharT and a size.

And the constructor has

Constructs a view of the first str.size() characters of the character array starting with the element pointed by str.data().

So if string_view just points to the underlying char array of the provided string then we will have a dangling pointer once the expression ends and the temporary is destroyed.

As pointed out in the comments one reason this behavior may have been allowed is so you can pass a string_view to a function and construct that string_view from a temporary string

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • That's what I first thought, but then why not just `string_view(const string&&) = delete;`, which will disable rvalues? – vsoftco Jan 29 '16 at 17:11
  • 1
    @vsoftco Write an LWG issue :) – T.C. Jan 29 '16 at 17:12
  • @T.C. I want first to make sure that it is indeed UB ;) – vsoftco Jan 29 '16 at 17:14
  • 3
    @vsoftco it is, but on second thought banning rvalues may significantly reduce usability for functions taking string view arguments. – T.C. Jan 29 '16 at 17:15
  • @T.C. Can you give an example? You mean that `func(string_view(rvalue))` will be OK? – vsoftco Jan 29 '16 at 17:18
  • 2
    Do note that the [similar GSL type `string_span`](https://github.com/Microsoft/GSL) does explicitly disallow using rvalues in various cases, for precisely this reason. Of course, this makes it hard to use in some cases, as T.C. points out; you have to create an explicit temporary. – Nicol Bolas Jan 29 '16 at 17:19
  • @vsoftco remember the standard doesn't always cath these things. Like when they had to change regex_search: http://stackoverflow.com/questions/33154890/simple-stdregex-search-code-wont-compile-with-apple-clang-std-c14/33155000#33155000 – NathanOliver Jan 29 '16 at 17:19
  • @vsoftco I think that example is one of the things T.C. was thinking of. – NathanOliver Jan 29 '16 at 17:20
  • 1
    @NathanOliver Sorry, I'm still a bit confused. Why will `func(string_view(rvalue))` work? The argument (i.e. the view) is copied into the parameter, which is later used inside the function. AFAIK, this should also be UB, as the original rvalue is long dead. Maybe I'm missing something here. – vsoftco Jan 29 '16 at 17:23
  • 3
    @vsoftco The rvalue should exist till the end of the expression and having the function execute and return is part of the expression so the rvalue should be alive the entire time. – NathanOliver Jan 29 '16 at 17:25
  • @NathanOliver Oh yes, sure, my confusion. It's dead at `;`. So indeed it's OK, thanks. – vsoftco Jan 29 '16 at 17:26
  • 1
    @NicolBolas iirc string_span is read-write, though. So it's kinda like non-const/const lvalue reference. – T.C. Jan 29 '16 at 17:36
  • @vsoftco `std::string f(); void g(string_view); g(f());`. In general, functions taking `string_view`s can't assume anything about the underlying string's lifetime anyway, so I'm not sure there's much point in banning creation from rvalues. – T.C. Jan 29 '16 at 19:37
  • @T.C. Thanks, I see what you mean. – vsoftco Jan 29 '16 at 19:43