Это UB, но не по той причине, о которой вы могли подумать.
Соответствующая подпись std::minmax()
:
template< class T >
std::pair<const T&,const T&> minmax( const T& a, const T& b );
В этом случае ваш pair
является парой ссылок на uintptr_t const
. Где настоящие объекты, на которые мы ссылаемся? Правильно, это были временные файлы, созданные в последней строке, которые уже вышли за рамки! У нас есть висящие ссылки.
Если вы написали:
return std::minmax(
reinterpret_cast<std::uintptr_t>(first),
reinterpret_cast<std::uintptr_t>(second)
).first;
тогда у нас нет висящих ссылок, и вы можете видеть, что gcc генерирует соответствующий код:
minPointer(void*, void*):
cmp rsi, rdi
mov rax, rdi
cmovbe rax, rsi
ret
В качестве альтернативы вы можете явно указать тип pair
как std::pair<std::uintptr_t, std::uintptr_t>
. Или просто полностью обойти пару и return std::min(...);
.
Что касается особенностей языка, вам разрешено преобразовывать указатель в достаточно большой целочисленный тип из-за [expr.reinterpret.cast]/4, а std::uintptr_t
гарантированно будет достаточно большим. Так что, как только вы исправите проблему с оборванной ссылкой, все будет в порядке.
person
Barry
schedule
17.09.2018
<
для сравнения указателей, если они не находятся в одном массиве или объекте; все остальное - УБ. - person underscore_d   schedule 17.09.2018minmax
заметок - немного далеко внизу - Для перегрузок (1,2), если один из параметров является значением r, возвращаемая ссылка становится висячей ссылкой в конце полного выражения, содержащего вызов - person underscore_d   schedule 17.09.2018pair
, а не к его членам) - person underscore_d   schedule 17.09.2018