Просто для полной ясности, вот Порядок оценки документ Jarod42, уже связанный, и соответствующая цитата:
14) В выражении вызова функции выражение, котороеназывает функцию упорядоченной перед каждым выражением аргумента и каждым аргументом по умолчанию.
Таким образом, мы должны прочитать выражение
return member->foo(renew());
как
return function-call-expression;
где выражение-вызова функции равно
{function-naming-expression member->foo} ( {argument-expression renew()} )
, поэтому выражение-имени-функции member->foo
равно секвенировано-до- выражение аргумента,В уже связанном документе написано:
Если A секвенируется до B, то оценка A будет завершена до того, как начнется оценка B.
, поэтому мы должны полностью оценить member->foo
первый.Я думаю, что он должен расшириться как
// 1. evaluate function-naming-expression
auto tmp_this_member = this->member;
int (B::*tmp_foo)(int) = tmp_this_member->foo;
// 2. evaluate argument expression
int tmp_argument = this->renew();
// 3. make the function call
(tmp_this_member->*tmp_foo) ( tmp_argument );
... это именно то, что вы видите.Это последовательность, требуемая C ++ 17, и до этого последовательность и поведение были неопределенными.
tl; dr компилятор прав, и этот код будетбудь противен, даже если это сработало.