[c++] присваивание временной переменной

elenangel

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

#include <string>

int main
{
std::string s("test");
std::string = s;
return 0;
}

apl13

Как сделать чтобы ругался?
Удалить copy constructor? :o

elenangel

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

PooH

Удалить copy constructor?
а разве тут copy constructor будет вызываться?
не operator=?

apl13

а разве тут copy constructor будет вызываться?
Да нет, это я так.

doublemother

Сделать explicit copy constructor и забанить оператор =.

dazzler

Для того, чтобы запретить присваивание временным объектам, нужно было бы объявить operator = вне класса, а этого делать нельзя по стандарту.
Пример:
class A
{
public:
void operator << (const A&) { }
};

void operator < (A&, const A&) { }

void test
{
A a;
A << a;
A < a; // no match for 'operator<' in 'A < a'
}

apl13

почему такое возможно и на это не ругается компилятор?
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n324...
Как сделать чтобы ругался?
Могу в качестве развратного рецепта предложить запретить использовать внутренные конструкторы и перейти к внешним:
#include <string>

inline const std::string stdString { return std::string; }
inline const std::string stdString(char const *s) { return std::string(s); }

int main {
std::string s(stdString("test";
stdString = s;
return 0;
}

(Первая строчка в мейне не то чтобы конструкция, она просто для демонстрации того, что присваивание именованным объектам по-прежнему работает, а все temporaries, см. следующую строчку, теперь константные.)
Но это стайлгайд переделывать.

Maurog

почему такое возможно и на это не ругается компилятор? Как сделать чтобы ругался?
надо с этим жить :grin:
смотри на это, как на вызов неконст метода у временного объекта.

std::string.do_something(bla-bla);

не вижу причин запрещать такое или даже выдавать предупреждение

Maurog

Да нет, это я так.
лично для меня было не очевидно что же реально используется
оказалось, что если имя у переменной есть, то работает copy initialization, а если безымянный объект, то срабатывает конструктор + operator=
смотрим:
http://liveworkspace.org/code/4hfkIi%243

apl13

оказалось, что если имя у переменной есть, то работает copy initialization, а если безымянный объект, то срабатывает конструктор + operator=
смотрим:
Да дело даже не в имени.
Просто std::string — это выражение, результат которого есть уже готовая строка, поэтому там assignment operator.
В std::string s = std::string никаких таких выражений слева нет, именованный объект, остается только семантика конструкции.

erotic

void operator < (A&, const A&) { }
Гениально - давайте запретим сравнивать константные объекты.

Serab

а почему, кстати, не вызывается этот оператор-то? Т.е. присвоить можно, а оператор < такой вызвать нельзя, в чем прикол?

elenangel

вообще-то это он для примера оператор перегрузил, никто не предлагает запрещать сравнивать.

ppplva

Пользуйте clang:
1.cc:15:7: error: invalid operands to binary expression ('A' and 'A')
A < a;
~~~ ^ ~
1.cc:7:6: note: candidate function not viable: expects an l-value for 1st argument
bool operator<(A&, const A&) {
^

Точно так же нельзя написать
 A& ref = A; 
  error: non-const lvalue reference to type 'A' cannot bind to a temporary of type 'A'
A& ref = A;
^ ~~~

dazzler

а почему, кстати, не вызывается этот оператор-то? Т.е. присвоить можно, а оператор < такой вызвать нельзя, в чем прикол?
Тут есть немного флуда на эту тему: http://stackoverflow.com/questions/1565600/how-come-a-non-const-reference-cannot-bind-to-a-temporary-object
Вкратце:
The C++ committee decided it doesn't make sense to modify temporaries, therefore, they disallowed binding to non-const references.
Но для операторов-членов класса это ограничение не работает, так как this при вызове метода передаётся просто как указатель (если я правильно понимаю).

Serab

так как this при вызове метода передаётся просто как указатель (если я правильно понимаю).
константность this определяется же по тому, стоит после метода квалификатор const или нет.

Serab

ну в принципе ответ на SO меня устроил, просто не знал о такой особенности, спасибо.
Оставить комментарий
Имя или ник:
Комментарий: