Взятие адреса временного объекта

§5.3.1 Унарные операторы, раздел 3

Результат одинарный & Оператор является указателем на свой операнд. Операндом должно быть lvalue или квалифицированный идентификатор.

Что именно означает "должен быть" в этом контексте? Значит ли это ошибочно брать адрес временного? Мне было просто интересно, потому что g++ только предупреждает меня, а comeau отказывается компилировать следующую программу:

#include <string>

int main()
{
    &std::string("test");
}

g++ предупреждение: taking address of temporary

comeau ошибка: expression must be an lvalue or a function designator

Кто-нибудь имеет компилятор Microsoft или другие компиляторы и может протестировать эту программу, пожалуйста?

Ответ 1

Слово "должно" на стандартном языке означает строгое требование. Итак, да, ваш код плохо сформирован (это ошибка), потому что он пытается применить оператор адреса к не-lvalue.

Однако проблема здесь не в попытке получить адрес временного. Проблема заключается, опять же, в принятии адреса не-lvalue. Временный объект может быть lvalue или non-lvalue в зависимости от выражения, которое создает это временное или обеспечивает доступ к этому временному. В вашем случае у вас есть std::string("test") - функциональный стиль, отлитый от не ссылочного типа, который по определению создает не-lvalue. Отсюда ошибка.

Если вы хотите получить адрес временного объекта, вы могли бы обойти это ограничение, выполнив это, например

const std::string &r = std::string("test");
&r; // this expression produces address of a temporary

при этом возвращаемый указатель остается действительным до тех пор, пока существует временное. Существуют и другие способы юридического получения адреса временного объекта. Просто ваш конкретный метод оказывается незаконным.

Ответ 2

Когда слово "должно" используется в стандарте С++, это означает "нужно от боли смерти" - если реализация не подчиняется этому, она ошибочна.

Ответ 3

Это разрешено в MSVC с опцией устаревших /Ze (расширения). Это было разрешено в предыдущих версиях MSVC. Он генерирует диагностику с включенными предупреждениями:

предупреждение C4238: используется нестандартное расширение: класс rvalue используется как lvalue.

Если параметр /Za не используется (соблюдение совместимости ANSI), выполните следующие действия:

ошибка C2102: '&' требуется l-значение

Ответ 4

&std::string("test"); запрашивает адрес возвращаемого значения вызова функции (мы будем игнорировать как несущественный факт, что эта функция является ctor). У него не было адреса, пока вы его не присвоили. Следовательно, это ошибка.

Ответ 5

Стандарт С++ на самом деле является требованием к совместимым реализациям С++. В местах написано, чтобы различать код, который должны принимать согласованные реализации, и код, для которого соответствующие реализации должны давать диагностику.

Таким образом, в этом конкретном случае соответствующий компилятор должен дать диагностику, если будет принят адрес rvalue. Оба компилятора делают, поэтому они соответствуют друг другу в этом отношении.

Стандарт не запрещает создание исполняемого файла, если определенный ввод вызывает диагностику, то есть предупреждения являются допустимой диагностикой.

Ответ 6

Я не эксперт по стандартам, но это, безусловно, звучит как ошибка для меня. g++ очень часто дает предупреждение только для вещей, которые действительно являются ошибками.

Ответ 7

пользовательское преобразование

struct String {
    std::string str;

    operator std::string*() {
        return &str;
    }
};

std::string *my_str = String{"abc"};