Когда я работаю со своими любимыми контейнерами, я склонен к цепным операциям. Например, в хорошо известной Стереть-удалить идиому:
v.erase( std::remove_if(v.begin(), v.end(), is_odd), v.end() );
Из того, что я знаю о порядке оценки, v.end()
(на rhs) могут быть оценены до призыв к std::remove_if
, Это не проблема здесь, так как std::remove*
только перемешать вектор без изменения его конечного итератора.
Но это может привести к действительно удивительным конструкциям, как, например, (демонстрация):
#include <iostream>
struct Data
{
int v;
int value() const { return v; }
};
auto inc(Data& data) { return ++data.v; }
void print_rhs(int, int value) { std::cout << value << '\n'; }
int main()
{
Data data{0};
print_rhs(inc(data), data.value()); // might print 0
}
Это удивительно, так как print_rhs
называется после inc
был вызван; что значит data.v
является 1
когда print_rhs
называется. Тем не менее, так как data.value()
может быть оценено до, 0
это возможный вывод.
Я думаю, что это может быть хорошим улучшением, если порядок оценки будет менее удивительным; в частности, если аргументы функции с побочными эффектами были оценены раньше, чем без.
Мои вопросы тогда:
Обсуждали ли когда-нибудь это изменение или предложили в комитете по С ++?
Наверное.
Вы видите какие-либо проблемы, которые это может принести?
Да. Это может уменьшить возможности оптимизации, которые существуют сегодня, и не приносит никакой прямой выгоды, кроме возможности писать больше однострочников. Но в любом случае однострочники не очень хорошая вещь, так что это предложение, вероятно, никогда не пройдет -99 баллов.
Других решений пока нет …