C++
std::minmax
std::tie
programming
coding practices

Is there a nice way to assign stdminmaxa, b to stdtiea, b?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Assigning the result of std::minmax(a, b) directly to std::tie(a, b) to sort two variables in place seems intuitive, but it contains a subtle bug: std::minmax returns references to its arguments, and assigning through std::tie modifies those same variables during the assignment, causing undefined behavior. C++17 structured bindings and careful use of temporaries provide safe alternatives.

The Naive (Broken) Approach

cpp
1#include <algorithm>
2#include <tuple>
3
4int a = 7, b = 3;
5
6// DANGER: undefined behavior!
7std::tie(a, b) = std::minmax(a, b);

This looks clean but is broken. std::minmax(a, b) returns std::pair<const int&, const int&> — references to a and b. When std::tie(a, b) assigns the first element (the min), it modifies a. Now the second reference (the max) may point to the already-modified value.

Why It Fails

Step by step with a = 7, b = 3:

  1. std::minmax(a, b) returns {ref to b (3), ref to a (7)}
  2. std::tie(a, b) assigns first: a = 3 (from ref to b) — OK so far
  3. std::tie(a, b) assigns second: b = ref to a — but a is now 3, so b = 3
  4. Result: a = 3, b = 3 — wrong! Expected a = 3, b = 7

Safe Solutions

Solution 1: Use std::minmax with an Initializer List

cpp
1int a = 7, b = 3;
2
3// Initializer list forces copies — safe
4auto [lo, hi] = std::minmax({a, b});
5a = lo;
6b = hi;
7// a = 3, b = 7

The initializer list version copies the values into a temporary std::initializer_list, breaking the reference chain.

Solution 2: Simple if-swap

For just two variables, the simplest and most readable approach:

cpp
1int a = 7, b = 3;
2
3if (a > b) {
4    std::swap(a, b);
5}
6// a = 3, b = 7

This is zero-overhead, completely safe, and communicates intent clearly.

Solution 3: std::tie with Explicit Copies

Force copies before assignment:

cpp
1int a = 7, b = 3;
2
3std::tie(a, b) = std::make_pair(std::min(a, b), std::max(a, b));
4// a = 3, b = 7

std::make_pair creates a pair<int, int> (values, not references), so the assignment is safe.

Solution 4: Structured Bindings with a Temporary

cpp
1int a = 7, b = 3;
2
3auto result = std::minmax(a, b);  // pair<const int&, const int&>
4auto lo = result.first;           // copy the value
5auto hi = result.second;          // copy the value
6a = lo;
7b = hi;

Understanding std::minmax Return Types

The key to understanding the bug is knowing what std::minmax returns:

cpp
1// Two-argument version — returns references
2template<class T>
3std::pair<const T&, const T&> minmax(const T& a, const T& b);
4
5// Initializer list version — returns values
6template<class T>
7std::pair<T, T> minmax(std::initializer_list<T> ilist);

The two-argument version returns references for efficiency. The initializer list version returns values because the initializer list is temporary.

Comparison of Approaches

ApproachSafe?CopiesReadability
std::tie(a,b) = std::minmax(a,b)No0Looks clean but broken
auto [lo,hi] = std::minmax({a,b})Yes2Good
if (a > b) std::swap(a, b)Yes0-1Best
std::tie(a,b) = std::make_pair(min,max)Yes2Verbose but safe

Common Pitfalls

  • Dangling references: std::minmax with two arguments returns references. If the arguments are temporaries, the references dangle immediately: auto [lo, hi] = std::minmax(getA(), getB()); is undefined behavior.
  • Structured bindings with references: auto& [lo, hi] = std::minmax(a, b) binds references to a and b. Modifying a or b later changes what lo and hi see.
  • Floating-point NaN: std::minmax with NaN values has implementation-defined behavior. NaN comparisons always return false.
  • C++20 ranges::minmax: std::ranges::minmax returns a ranges::minmax_result struct. The same reference aliasing issue applies to the two-argument overload.

Summary

  • std::tie(a, b) = std::minmax(a, b) is undefined behavior because minmax returns references that alias the assignment targets
  • Use if (a > b) std::swap(a, b) for the simplest, safest two-variable sort
  • Use std::minmax({a, b}) (initializer list) if you need both min and max as values
  • The root cause is that std::minmax(a, b) returns pair<const T&, const T&>, not pair<T, T>

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.