Ответ 1
Это 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
гарантированно будет достаточно большим. Поэтому, как только вы исправите проблему оборванных ссылок, вы в порядке.