Конечно, это очень странный код и писать подобное в проде недопустимо. Но если говорить о его нормативном статусе, то тут есть нюансы.
В C++20 этот код корректен: согласно [class.temporary#6], время жизни
std::vector<int>{42, 17, 13}, являющегося временным объектов, продлевается до конца цикла for, так что мы можем безопасно по нему итерироваться. Временный же объект std::scoped_lock{m} создается и сразу уничтожается: для него не применимо ни одно из правил продления жизни.В C++23 же существующее поведение было изменено: P2644R1 добавил в стандарт следующий пункт:
> There are
> The fourth context is when a temporary object other than a function parameter object is created in the for-range-initializer of a range-based for statement. If such a temporary object would otherwise be destroyed at the end of the for-range-initializer full-expression, the object persists for the lifetime of the reference initialized by the for-range-initializer.
То есть, теперь времена жизни всех (за незначительными исключениями) объектов, созданных в инициализаторе range-based for, продлеваются до конца цикла. Так что если рассматривать приведенный выше код: мы создаем временный объект
std::scoped_lock{m}, чье время жизни продлевается до конца цикла; после чего создаем временный объект std::vector<int>{42, 17, 13}, время жизни которого продлевается так же; и дальше в цикле на первой же итерации создаем новый объект std::scoped_lock guard{m}, захватывающий мьютекс, который уже был захвачен предыдущим std::scoped_lock — и тем самым получаем состояние взаимной блокировки (deadlock), которое стандартом определяется как неопределенное поведение.