GEOS
Format.hpp
1 /*
2  * ------------------------------------------------------------------------------------------------------------
3  * SPDX-License-Identifier: LGPL-2.1-only
4  *
5  * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC
6  * Copyright (c) 2018-2024 TotalEnergies
7  * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University
8  * Copyright (c) 2023-2024 Chevron
9  * Copyright (c) 2019- GEOS/GEOSX Contributors
10  * All rights reserved
11  *
12  * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details.
13  * ------------------------------------------------------------------------------------------------------------
14  */
15 
16 #ifndef GEOS_COMMON_FORMAT_HPP_
17 #define GEOS_COMMON_FORMAT_HPP_
18 
19 #include <type_traits>
20 #include <optional>
21 
22 #if __cplusplus < 202002L
23 #define GEOS_USE_FMT
24 #endif
25 
26 #ifdef GEOS_USE_FMT
27 #ifndef FMT_HEADER_ONLY
28 #define FMT_HEADER_ONLY
29 #endif
30 // Differentiate between standalone fmt path and umpire's fmt path
31 #include "../include/fmt/core.h"
32 #include "../include/fmt/chrono.h"
33 #include "../include/fmt/ranges.h"
34 #include "../include/fmt/xchar.h"
35 #define GEOS_FMT_NS fmt
36 #else // use C++20's <format>
37 #include <format>
38 #define GEOS_FMT_NS std
39 #endif
40 
41 #ifdef GEOS_USE_FMT
47 template< typename T >
48 struct fmt::formatter< T, std::enable_if_t< std::is_enum< T >::value > >
49 {
56  template< typename ParseContext >
57  constexpr auto parse( ParseContext & ctx )
58  {
59  return ctx.end();
60  }
61 
69  template< typename FormatContext >
70  auto format( const T & value, FormatContext & ctx ) const
71  {
72  return fmt::format_to( ctx.out(), "{}", static_cast< std::underlying_type_t< T > >( value ) );
73  }
74 };
75 #endif
76 
81 #define GEOS_FMT( msg, ... ) GEOS_FMT_NS::format( msg, __VA_ARGS__ )
82 
90 #define GEOS_FMT_TO( iter, size, msg, ... ) *GEOS_FMT_NS::format_to_n( iter, size - 1, msg, __VA_ARGS__ ).out = '\0'
91 
96 
101 template< typename T >
102 struct GEOS_FMT_NS::formatter< std::optional< T > > : GEOS_FMT_NS::formatter< T >
103 {
110  auto format( std::optional< T > const & opt, format_context & ctx ) const
111  {
112  if( opt )
113  {
114  return GEOS_FMT_NS::formatter< T >::format( *opt, ctx );
115  }
116  return GEOS_FMT_NS::format_to( ctx.out(), "" );
117  }
118 };
119 
121 
122 // The following workaround is needed to fix compilation with NVCC on some PowerPC machines.
123 // The issue causes the following assertion error message:
124 // "Cannot format an argument. To make type T formattable provide a formatter<T> specialization"
125 // The standard definition of the has_const_formatter check of fmt fails due to a compiler bug, see the issue below:
126 // https://github.com/fmtlib/fmt/issues/2746
127 // The workaround was originally implemented in fmt:
128 // https://github.com/fmtlib/fmt/commit/70de324aa801eaf52e94c402d526a3849797c620
129 // but later removed:
130 // https://github.com/fmtlib/fmt/commit/466e0650ec2d153d255a40ec230eb77d7f1c3334
131 // This workaround bypasse the check for a const formatter whenever the foramt context GEOS_FMT_NS::format_context is used
132 #ifdef GEOS_USE_FMT_CONST_FORMATTER_WORKAROUND
133 template< >
134 constexpr auto GEOS_FMT_NS::detail::has_const_formatter_impl< GEOS_FMT_NS::format_context >( ... ) -> bool
135 {
136  return true;
137 }
138 #endif // End of the workaround for fmt compilation issues
139 
143 #if __cplusplus < 202002L
144 template< class T >
145 static constexpr bool has_formatter_v = fmt::has_formatter< fmt::remove_cvref_t< T >, fmt::format_context >();
146 #else
147 template< typename T >
148 concept has_formatter_v = requires ( T& v, std::format_context ctx )
149 {
150  std::formatter< std::remove_cvref_t< T > >().format( v, ctx );
151 };
152 #endif
153 
154 #endif //GEOS_COMMON_FORMAT_HPP_
auto format(std::optional< T > const &opt, format_context &ctx) const
Format the std::optional<T> to a string.
Definition: Format.hpp:110
auto format(const T &value, FormatContext &ctx) const
Formatter for the fmtlib formatting library.
Definition: Format.hpp:70
constexpr auto parse(ParseContext &ctx)
Parser for the fmtlib formatting library.
Definition: Format.hpp:57