Puzzle #4 (based on C++17)
Purpose of this puzzle is to explain "why we can't get rid of make_pair and make_tuple functions? Since C++17 we have deduction guides for classes".
Deduction guides would be perfectly enough in most of the cases. make_pair and make_tuple are useful when we're dealing with reference_wrappers but we want to have e.g. pair of references, not reference_wrappers.
make_pair and make_tuple are able to recognize such situation and instead of creating e.g.
pair<reference_wrapper<int>, reference_wrapper<int>> it'll return pair<int&, int&>.
Of course there are use cases when we want to have pair with reference_wrapper[s]. Then we always can explicitly say it to the compiler, e.g. by using mentioned deduction guides.

Back to the puzzle. Such types will be deduced by compiler:
decltype(auto) a = 0; // int
decltype(auto) b = std::ref(a); // std::reference_wrapper<int>

auto f1 = foo(a, b); // foo<int, std::reference_wrapper<int>>
auto f2 = make_foo(a, b); // foo<int, std::reference_wrapper<int>>

auto p1 = std::pair(a, b); //std::pair<int, std::reference_wrapper<int>> 
auto p2 = std::make_pair(a, b); // std::pair<int, int&> 

auto t1 = std::tuple(a, b); //std::tuple<int, std::reference_wrapper<int>> 
auto t2 = std::make_tuple(a, b); // std::tuple<int, int&> 
As you can see p1, p2 and t1, t2 have different types. That's why two last is_same_v print zeros (false).
#include <tuple>
#include <utility>
#include <functional>
#include <iostream>

template <typename A, typename B>
struct foo
  foo(A, B) {};

template <typename A, typename B>
auto make_foo(A&& a, B&& b)
  return foo{ std::forward<A>(a), std::forward<B>(b) };

int main()
  decltype(auto) a = 0;
  decltype(auto) b = std::ref(a);

  auto f1 = foo(a, b);
  auto f2 = make_foo(a, b);

  auto p1 = std::pair(a, b);
  auto p2 = std::make_pair(a, b);

  auto t1 = std::tuple(a, b);
  auto t2 = std::make_tuple(a, b);

  std::cout << std::is_same_v<decltype(f1), decltype(f2)>;
  std::cout << std::is_same_v<decltype(p1), decltype(p2)>;
  std::cout << std::is_same_v<decltype(t1), decltype(t2)>;
With given code and C++17 compiler, pick one answer:
Guaranteed to print: 000
Guaranteed to print: 001
Guaranteed to print: 010
Guaranteed to print: 011
Guaranteed to print: 100
Guaranteed to print: 101
Guaranteed to print: 110
Guaranteed to print: 111
Guaranteed to print something else
Undefined bahaviour
Implementation defined
Will not compile