0

I was reading Chapter 9 of the 2nd edition of A Tour of C++ by Bjarne Stroustrup and was puzzled by the use of {&king[0],2} where king is a string variable. I get that it returns the first 2 strings but I don't know what the name is for this to look up more details about it like:

  • Does the & ampersand indicate that it is a reference or does it switch it to pointer?
  • In what version was this feature introduced? I know the book is based on C++17 but don't know what version began supporting it.
// Strings and Regular Expressions
#pragma once
#include <string>


using namespace std;

string cat(string_view sv1, string_view sv2) {
    string res(sv1.length()+sv2.length(), '\0');
    char* p = &res[0];

    for (char c : sv1)                  // one way
        *p++ = c;
    copy(sv2.begin(), sv2.end(), p);    // another way
    return res;
}

void tryCat() {
    string king = "Harold";
    auto s1 = cat(king, "William");             // string and const char*
    auto s2 = cat(king, king);                  // string and string
    auto s3 = cat("Edward", "Stephen"sv);       // const char* and string_view
    auto s4 = cat("Canute"sv, king); 
    auto s5 = cat({&king[0],2}, "Henry"sv);     // HaHenry
    auto s6 = cat({&king[0],2}, {&king[2],4});  // Harold     
    cout << s6 << endl;
}

int main () {
    tryCat();
}
heretoinfinity
  • 1,528
  • 3
  • 14
  • 33
  • The `&` just accesses the address of an object. But I think it is considered inappropriate, (someone can chime in on that.) Better to use `std::addressof(...)`. – lakeweb Feb 10 '22 at 23:14
  • @lakeweb, `std::addressof` is typically for generic code where you don't know whether the type has `&` overloaded and you want to guarantee you get the address rather than the behaviour the type decided was appropriate for regular uses of `&`. – chris Feb 10 '22 at 23:28
  • 1
    Thanks @chris, I was thinking of the instance of an iterator `&*it`. There was a discussion I had followed and I think that's where it came up. – lakeweb Feb 10 '22 at 23:37
  • @lakeweb, could you link the discussion if you remember it? – heretoinfinity Feb 11 '22 at 00:47
  • 1
    `{&king[0],2}` uses `&king[0]` (the address of `king[0]`) and the `int` literal `2` to initialise an object. Since that is being passed as the first argument of `cat()`, and `cat()` expects a first argument of type `std::string_view`, the object being constructed/initialised is a `std::string_view`. Since `std::string_view` itself was introduced in C++17, your code assumes C++17 or greater. Ignoring the use of `string_view`, the construct is a list initialiser, and list initialisers were introduced in C++11. – Peter Feb 11 '22 at 01:17
  • 1
    Hi @heretoinfinity, I copied this part of the comments to my notes, so if I run across it... It was in a boost::spirit::x3 post as I recall. sehe was in on it. – lakeweb Feb 11 '22 at 01:24

2 Answers2

2

The funcction

string cat(string_view sv1, string_view sv2) {

accepts as its arguments two objects of the type std::string_view.

Such a construction

{&king[0],2}

is used to construct an object of the type std::string_view using the constructor

constexpr basic_string_view(const charT* str, size_type len);

The expression &king[0] in the above construction has the pointer type char * and yields the address of the first character of a string.

As the variable king is declared like

string king = "Harold";

then in fact the object of the type std::string_view is built from first two characters of the string like "Ha".

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
1

I think it's called copy-list-initialization, specifically form #7 at List initialization - Cppreference. Copy-list-initialization was introduced in C++11.

function( { arg1, arg2, ... } )           (7)

&king[0] gets the underlying char* array from the std::string. &king[2] gets the address of the third character of that array. In this case, & is the address-of operator, not a reference. [0] is a subscript. The second item in the braces after the comma is the second argument to the string_view constructor which specifies the length of the string.

Here's the description of copy-list-initialization from the cppreference link.

copy-list-initialization (both explicit and non-explicit constructors are considered, but only non-explicit constructors may be called)

  1. initialization of a named variable with a braced-init-list after an equals sign
  2. in a function call expression, with braced-init-list used as an argument and list-initialization initializes the function parameter
Nathan Mills
  • 2,243
  • 2
  • 9
  • 15