SpECTRE Documentation Coverage Report
Current view: top level - Parallel - Printf.hpp Hit Total Coverage
Commit: 8ec8f22653343473314d70693973649cd4f5bd62 Lines: 3 3 100.0 %
Date: 2024-04-16 20:43:37
Legend: Lines: hit not hit

          Line data    Source code
       1           1 : // Distributed under the MIT License.
       2             : // See LICENSE.txt for details.
       3             : 
       4             : /// \file
       5             : /// Defines Parallel::printf for writing to stdout
       6             : 
       7             : #pragma once
       8             : 
       9             : #include <charm++.h>
      10             : #include <iomanip>
      11             : #include <limits>
      12             : #include <sstream>
      13             : #include <string>
      14             : #include <type_traits>
      15             : #include <utility>
      16             : 
      17             : #include "Utilities/ErrorHandling/FloatingPointExceptions.hpp"
      18             : #include "Utilities/Requires.hpp"
      19             : #include "Utilities/TypeTraits/IsStreamable.hpp"
      20             : 
      21             : namespace Parallel {
      22             : namespace detail {
      23             : /*!
      24             :  * Fundamentals and pointers are already printable so there is no conversion
      25             :  * to a std::string necessary.
      26             :  */
      27             : template <typename T,
      28             :           Requires<std::is_fundamental<std::decay_t<
      29             :                        std::remove_pointer_t<std::decay_t<T>>>>::value or
      30             :                    std::is_pointer<T>::value or
      31             :                    std::is_pointer<std::decay_t<T>>::value> = nullptr>
      32             : inline constexpr T stream_object_to_string(T&& t) {
      33             :   return t;
      34             : }
      35             : 
      36             : /*!
      37             :  * Stream an object of type `T` into a std::stringstream and return it as a
      38             :  * std::string so that it is printable by calling `.c_str()` on it.
      39             :  * We need a 2-phase call so that the std::string doesn't go out of scope before
      40             :  * the C-style string is passed to printf.
      41             :  */
      42             : template <typename T,
      43             :           Requires<std::is_class<std::decay_t<T>>::value or
      44             :                    std::is_enum<std::decay_t<T>>::value> = nullptr>
      45             : inline std::string stream_object_to_string(T&& t) {
      46             :   using ::operator<<;
      47             :   static_assert(tt::is_streamable<std::stringstream, T>::value,
      48             :                 "Cannot stream type and therefore it cannot be printed. Please "
      49             :                 "define a stream operator for the type.");
      50             :   std::stringstream ss;
      51             :   ss << std::setprecision(std::numeric_limits<double>::digits10 + 4)
      52             :      << std::scientific << t;
      53             :   return ss.str();
      54             : }
      55             : 
      56             : /*!
      57             :  * Fundamentals are already printable, so nothing to do.
      58             :  */
      59             : template <typename T,
      60             :           Requires<std::is_fundamental<std::decay_t<
      61             :               std::remove_pointer_t<std::decay_t<T>>>>::value> = nullptr>
      62             : inline constexpr T get_printable_type(T&& t) {
      63             :   return t;
      64             : }
      65             : 
      66             : /*!
      67             :  * Get the pointer of the std::string so it can be passed to CkPrintf which
      68             :  * only works on fundamentals
      69             :  */
      70             : inline const typename std::string::value_type* get_printable_type(
      71             :     const std::string& t) {
      72             :   return t.c_str();
      73             : }
      74             : 
      75             : template <typename Printer, typename... Ts>
      76             : inline void print_helper(Printer&& printer, const std::string& format,
      77             :                          Ts&&... t) {
      78             :   // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
      79             :   printer(format.c_str(), get_printable_type(std::forward<Ts>(t))...);
      80             : }
      81             : 
      82             : template <typename Printer, typename... Args>
      83             : inline void call_printer(Printer&& printer, const std::string& format,
      84             :                          Args&&... args) {
      85             :   const ScopedFpeState disable_fpes(false);
      86             :   print_helper(printer, format,
      87             :                stream_object_to_string(std::forward<Args>(args))...);
      88             : }
      89             : }  // namespace detail
      90             : 
      91             : /*!
      92             :  * \ingroup ParallelGroup
      93             :  * \brief Print an atomic message to stdout with C printf usage.
      94             :  *
      95             :  * Similar to Python, you can print any object that's streamable by passing it
      96             :  * in as an argument and using the formatter "%s". For example,
      97             :  * \code
      98             :  * std::vector<double> a{0.8, 73, 9.8};
      99             :  * Parallel::printf("%s\n", a);
     100             :  * \endcode
     101             :  */
     102             : template <typename... Args>
     103           1 : inline void printf(const std::string& format, Args&&... args) {
     104             : #pragma GCC diagnostic push
     105             : #pragma GCC diagnostic ignored "-Wformat-nonliteral"
     106             : #pragma GCC diagnostic ignored "-Wformat-security"
     107             :   detail::call_printer(
     108             :       // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
     109             :       [](auto... a) { CkPrintf(a...); }, format, std::forward<Args>(args)...);
     110             : #pragma GCC diagnostic pop
     111             : }
     112             : 
     113             : /*!
     114             :  * \ingroup ParallelGroup
     115             :  * \brief Print an atomic message to stderr with C printf usage.
     116             :  *
     117             :  * See Parallel::printf for details.
     118             :  */
     119             : template <typename... Args>
     120           1 : inline void printf_error(const std::string& format, Args&&... args) {
     121             : #pragma GCC diagnostic push
     122             : #pragma GCC diagnostic ignored "-Wformat-nonliteral"
     123             : #pragma GCC diagnostic ignored "-Wformat-security"
     124             :   detail::call_printer(
     125             :       // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
     126             :       [](auto... a) { CkError(a...); }, format, std::forward<Args>(args)...);
     127             : #pragma GCC diagnostic pop
     128             : }
     129             : }  // namespace Parallel

Generated by: LCOV version 1.14