Skip to the content of the web site.

Utility library

These functions are found in the #include <utility> library.

These are useful functions that don't belong elsewhere, as they are simply general-purpose functions.

void std::swap( T &first, T &second )

As long as the two arguments are of the same time, this function will swap them. If you have declared your own class Class_name, this function will just swap the bits between the two objects. If you want to create a specialized version of this for your class, you will likely:

  1. define a member function void swap( Class_name &other ), and
  2. implement a public function in the std namespace; for example:
    namespace std {
      void swap( Class_name &first, Class_name &second ) {
        first.swap( second );
      }
    }
    

T std::exchange( T &first, T &&second )

This assigns the second argument to the first on the assumption that the second argument is going out of scope, and then the function returns the original value of the first argument.

The std::pair class the auto std::make_pair( T first, T second )

In many cases, a function may need to return two values, but it would be inconvenient to create a new class that describes the pair of return values. Instead, there is a common class that allows you to easily return two items: std::pair.

For example, suppose you want to create safe integer addition, subtraction and multiplication operations, so these need to return an integer value, but then a Boolean flag indicating whether or not the first argument is valid. This way, all possible correct answers can be returned, but when a false answer is returned, the user can quickly determine this:

   std::pair<int, bool> add( int m, int n );
   std::pair<int, bool> subtract( int m, int n );
   std::pair<int, bool> multiply( int m, int n );
   std::pair<int, bool> divide( int m, int n );
   std::pair<int, bool> remainder( int m, int n );

Next, these two functions can use the make_pair(...) "factory", as opposed to calling a constructor. In this case, the compiler determines the types of the two arguments, and creates an instance of a pair containing those two types, initialized with the two arguments. If these types match the return type, all is good:

    std::pair<int, bool> add( int m, int n ) {
      int result{ m + n };

      return std::make_pair(
        result, (
          (m <= 0) || (n <= 0) || (result > 0)
        ) && (
          (m >= 0) || (n >= 0) || (result < 0)
        )
      );
    }

    std::pair<int, bool> subtract( int m, int n ) {
      int result{ m - n };

      return std::make_pair(
        result, (
          (m <= 0) || (n >= 0) || (result > 0)
        ) && (
          (m >= 0) || (n <= 0) || (result < 0)
        )
      );
    }

    std::pair<int, bool> multiply( int m, int n ) {
      if ( (m == 0) || (n == 0) ) {
        return std::make_pair( 0, true );
      } else {
        int result{ m*n };

        return std::make_pair(
          result, (result/n) == m
        );
      }
    }

    std::pair<int, bool> divide( int m, int n ) {
      if ( n == 0 ) {
        return std::make_pair( 0, false );
      } else {
        return std::make_pair( m/n, true );
      }
    }

    std::pair<int, bool> remainder( int m, int n ) {
      if ( n == 0 ) {
        return std::make_pair( 0, false );
      } else {
        return std::make_pair( m%n, true );
      }
    }

In each case, the comparison is a Boolean-valued operation that returns either true or false.

Note, you may be curious as to how that logical expression determines the validity of the result of an addition (or subtraction). Essentially, the result is invalid if ((m < 0) && (n < 0) && (result >= 0)) or ((m > 0) && (n > 0) && (result <= 0)). Thus, the result is valid if this is false, or

 !(((m < 0) && (n < 0) && (result >= 0)) || ((m > 0) && (n > 0) && (result <= 0)))

You will learn that (because !(p || q) == (!p && !q)) this is equivalent to:

 !((m < 0) && (n < 0) && (result >= 0)) && !((m > 0) && (n > 0) && (result <= 0))

which is (because !(p && q && r) == (!p || !q || !r)) equivalent to:

 (!(m < 0) || !(n < 0) || !(result >= 0)) && (!(m > 0) || !(n > 0) || !(result <= 0))

which is (because, for example, !(m < 0) == (m >= 0)) equivalent to:

 ((m >= 0) || (n >= 0) || (result < 0)) && ((m <= 0) || (n <= 0) || (result > 0))

When using this, you can access the two results using the public member variables first and second; for example:

   int m{};
   std::cout << "Enter a number between -2147483648 and 2147483647: ";
   std::cin  >> m;

   int n{};
   std::cout << "Enter another such number: ";
   std::cin  >> n;

   auto result{ add( m, n ) };

   if ( result.second ) {
     std::cout << m << " + "
               << n << " = "
	       << result.first << std::endl;
   } else {
     std::cout << "The sum " << m << " + "
               << n << " causes an overflow."
	       << std::endl;
   }

You can view examples at utility library.