Standard types#

Sends and receives data of various standard types.

#include <cstdlib>
#include <complex>
#include <iostream>
#include <tuple>
#include <array>
#include <utility>
#include <mpl/mpl.hpp>

// print elements of a pair
template<typename ch, typename tr, typename T1, typename T2>
std::basic_ostream<ch, tr> &operator<<(std::basic_ostream<ch, tr> &out,
                                       const std::pair<T1, T2> &p) {
  return out << '(' << p.first << ',' << p.second << ')';
}

// helper function for printing all elements of a tuple/ an array
template<typename ch, typename tr, typename tuple, std::size_t... IS>
void print_tuple_impl(std::basic_ostream<ch, tr> &out, const tuple &t,
                      std::index_sequence<IS...> is) {
  auto print_element = [&](auto i, auto a) -> void {
    out << a << (i + 1 < is.size() ? "," : "");
  };
  [[maybe_unused]] std::initializer_list<int> _{(print_element(IS, std::get<IS>(t)), 0)...};
}

// print all elements of a tuple
template<typename ch, typename tr, typename... args>
std::basic_ostream<ch, tr> &operator<<(std::basic_ostream<ch, tr> &out,
                                       const std::tuple<args...> &t) {
  out << '(';
  print_tuple_impl(out, t, std::index_sequence_for<args...>{});
  return out << ')';
}

// print all elements of an array
template<typename ch, typename tr, typename ty, std::size_t s>
std::basic_ostream<ch, tr> &operator<<(std::basic_ostream<ch, tr> &out,
                                       const std::array<ty, s> &t) {
  out << '(';
  print_tuple_impl(out, t, std::make_integer_sequence<std::size_t, s>{});
  return out << ')';
}

// print a byte
template<typename ch, typename tr>
std::basic_ostream<ch, tr> &operator<<(std::basic_ostream<ch, tr> &out, const std::byte &t) {
  return out << std::to_integer<int>(t);
}

// send some item of a standard type
template<typename T>
void send(const mpl::communicator &comm, const T &x) {
  comm.send(x, 1);
}

// receive some item of a standard type
template<typename T>
void recv(const mpl::communicator &comm) {
  T x;
  comm.recv(x, 0);
  std::cout << "x = " << std::boolalpha << x << '\n';
}

int main() {
  const mpl::communicator &comm_world{mpl::environment::comm_world()};
  // run the program with two or more processes
  if (comm_world.size() < 2)
    comm_world.abort(EXIT_FAILURE);
  // process 0 sends
  if (comm_world.rank() == 0) {
    char t_1{'A'};
    send(comm_world, t_1);
    signed char t_2{'B'};
    send(comm_world, t_2);
    unsigned char t_3{'C'};
    send(comm_world, t_3);
    signed short int t_4{-1};
    send(comm_world, t_4);
    unsigned short int t_5{1};
    send(comm_world, t_5);
    signed int t_6{-10};
    send(comm_world, t_6);
    unsigned int t_7{10};
    send(comm_world, t_7);
    signed long int t_8{-100};
    send(comm_world, t_8);
    unsigned long int t_9{100};
    send(comm_world, t_9);
    signed long long int t_10{-1000};
    send(comm_world, t_10);
    unsigned long long int t_11{1000};
    send(comm_world, t_11);
    bool t_12{true};
    send(comm_world, t_12);
    float t_13{1.2345f};
    send(comm_world, t_13);
    double t_14{2.3456};
    send(comm_world, t_14);
    long double t_15{3.4567};
    send(comm_world, t_15);
    std::complex<float> t_16{1.2f, -1.2f};
    send(comm_world, t_16);
    std::complex<double> t_17{2.3, -2.3};
    send(comm_world, t_17);
    std::complex<long double> t_18{3.4, -3.4};
    send(comm_world, t_18);
    std::pair<int, double> t_19{-2, 0.1234};
    send(comm_world, t_19);
    std::tuple<int, std::complex<double>> t_20{-2, 0.1234};
    send(comm_world, t_20);
    std::array<int, 4> t_21{1, 2, 3, 4};
    send(comm_world, t_21);
    std::byte t_22{255};
    send(comm_world, t_22);
  }
  // process 1 receives
  if (comm_world.rank() == 1) {
    recv<char>(comm_world);
    recv<signed char>(comm_world);
    recv<unsigned char>(comm_world);
    recv<signed short int>(comm_world);
    recv<unsigned short int>(comm_world);
    recv<signed int>(comm_world);
    recv<unsigned int>(comm_world);
    recv<signed long int>(comm_world);
    recv<unsigned long int>(comm_world);
    recv<signed long long int>(comm_world);
    recv<unsigned long long int>(comm_world);
    recv<bool>(comm_world);
    recv<float>(comm_world);
    recv<double>(comm_world);
    recv<long double>(comm_world);
    recv<std::complex<float>>(comm_world);
    recv<std::complex<double>>(comm_world);
    recv<std::complex<long double>>(comm_world);
    recv<std::pair<int, double>>(comm_world);
    recv<std::tuple<int, std::complex<double>>>(comm_world);
    recv<std::array<int, 4>>(comm_world);
    recv<std::byte>(comm_world);
  }
  return EXIT_SUCCESS;
}