3 Вопрос: Является ли это добавление строки допустимым выражением?

вопрос создан в Wed, May 8, 2019 12:00 AM

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

std::string a; 
a += "Hello" + " "+"World"; // doesn't compile
std::string name = "Old";
a += "Hello" + name +"World"; // compiles
    
1
  1. Почему вы просто не попытались скомпилировать его, чтобы определить, является ли оно допустимым?
    2019-05-08 15: 50: 14Z
  2. @ JesperJuhl Чтобы быть справедливым, это не потому, что код компилирует, что он действителен.
    2019-05-08 15: 50: 58Z
  3. @ FrancoisAndrieux Конечно нет (насколько я знаю, вы знаете, я знаю). Но это позволило бы OP добавить дополнительную информацию: «он компилируется» или «он не компилируется с этой ошибкой: ...». И выполнение некоторого базового тестирования самостоятельно (например, «это вообще компилируется?») - хорошая привычка.
    2019-05-08 15: 53: 54Z
  4. Они (не я), вероятно, думали, что вы не провели достаточно исследований, прежде чем задавать вопрос. Это немного субъективно.
    2019-05-08 18: 58: 28Z
3 ответа                              3                         

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

"Hello" + " "+"World

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

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

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

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

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

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

#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.

    
4
2019-05-08 16: 16: 40Z
  1. Добро пожаловать, Влад!
    2019-05-08 15: 46: 56Z
  2. @ Вирсавия Спасибо. Я рад с вами познакомиться. :)
    2019-05-08 15: 48: 46Z
  3. Или вы можете просто написать a += "Hello" " " "World" или даже `` a + = "Hello World" `, если вы чувствуете приключения.
    2019-05-08 15: 49: 24Z
  4. @ DanM. Вы правы, но вопрос об операторе +.
    2019-05-08 15: 50: 00Z
  5. @ bruno: скрытые глубины. Обратите внимание, что если a += b действительно будет заменено на a = a + b, код будет скомпилирован.
    2019-05-08 15: 50: 00Z

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

Вы можете использовать += с 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
2019-05-08 15: 52: 53Z
  1. Почему компилируется второй пример?
    2019-05-08 15: 56: 55Z
  2. @ ash007 Это языковая функция , хотя и малоизвестный.
    2019-05-08 16: 04: 26Z
  3. 2019-05-08 16: 05: 18Z
  4. Спасибо @Lightness ...
    2019-05-08 17: 45: 34Z

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

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

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

    
2
2019-05-08 15: 52: 05Z
источник размещен Вот