Является ли это добавление строки допустимым выражением? - PullRequest
1 голос
/ 08 мая 2019

Мне было любопытно, допустимы ли составные операторы присваивания для нескольких параметров.Я предполагаю, что + = не будет иметь побочных эффектов, но может не совпадать с «- =». ​​

std::string a; 
a += "Hello" + " "+"World"; // doesn't compile
std::string name = "Old";
a += "Hello" + name +"World"; // compiles

Ответы [ 3 ]

4 голосов
/ 08 мая 2019

Составной оператор присваивания += не входит в него.

Вы можете использовать += с std::string, потому что определяет соответствующую перегрузку , но получает только один аргумент.

И вы пытались передать в качестве этого аргумента выражение, построенное из + из нескольких строковых литералов. Это не скомпилируется.

Некоторые варианты, в этом игрушечном кейсе, которые могут вдохновить на решение для любого вашего реального кейса:

Вариант 1

// Multiple calls to +=
std::string a;
a += "Hello";
a += " ";
a += "World";

Вариант 2

// String literal concatenation!
std::string a; 
a += "Hello" " " "World";

Вариант 3

// Repeated std::string concat
std::string a;
a += std::string("Hello") + " " + "World";

Вариант 4

// Same
using namespace std::string_literals;
std::string a; 
a += "Hello"s + " " + "World";

Вариант 5

// Don't bother
std::string a;
a += "Hello World";
4 голосов
/ 08 мая 2019

Это недопустимое выражение, потому что нет оператора + для строковых литералов

"Hello" + " "+"World

(точнее для указателей, потому что в выражениях строковые литералы с редкими исключениями преобразуются в указатели на свои первые символы.)

Вместо этого вы можете написать

std::string a; 
( ( a += "Hello" ) += " " ) += "World";

Но было бы более читабельно, если написать

a += "Hello";
a += " ";
a += "World";

Или, как @ Вирсавия указала в (ценном) комментарии к моему ответу, вы можете использовать определяемый пользователем строковый литерал следующим образом

#include <string>
#include <iostream>

int main()
{
    using namespace std::string_literals;
    std::string a; 
    a += "Hello"s + " " + "World";

    std::cout << a << '\n';
}

Что касается этого утверждения

a += "Hello" + name +"World";

тогда его можно переписать с использованием операторов, определенных для класса std::basic_string

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+(basic_string<charT, traits, Allocator>&& lhs, const charT* rhs);

как

a += operator +( operator +( "Hello", name ), "World" ); 

Например

#include <string>
#include <iostream>

int main()
{
    std::string a;
    std::string name = "Old";

    a += operator +( operator +( "Hello ", name ), " World" ); 

    std::cout << a << '\n';
}

Учтите, что каждый оператор возвращает объект типа std::basic_string, для которого определен operator +. То есть в каждом вызове операторов в качестве аргумента присутствует объект типа std::basic_string.

2 голосов
/ 08 мая 2019

Выражение a += "Hello" + " " + "World" является сгруппированным как a += ("Hello" + " " + "World").

Правая часть представляет собой набор из 3 const char[] литералов.Они уменьшаются до const char* указателей при применении к двоичному сложению.Поскольку вы не можете добавлять указатели, компилятор должен выдавать диагностику.

(Обратите внимание, что якобы эквивалентное выражение a = a + "Hello" + " " + "World" компилируется.)

...