Improve I/O

- `IO::oformat` can display triangulations vertex handles
  with point, using `With_point_tag{}` as second argument,

- improve the compatibility with C++20 `<format>`: now the precision
  can be specified in the format string.

Backport: master
This commit is contained in:
Laurent Rineau 2023-03-08 16:54:47 +01:00
parent 0f8e3eb955
commit 98f1e53020
5 changed files with 75 additions and 24 deletions

View File

@ -293,7 +293,9 @@ using std::max;
// Macros to detect features of clang. We define them for the other // Macros to detect features of clang. We define them for the other
// compilers. // compilers.
// See https://clang.llvm.org/docs/LanguageExtensions.html // See https://clang.llvm.org/docs/LanguageExtensions.html
// See also https://en.cppreference.com/w/cpp/experimental/feature_test //
// Some of those macro have been standardized. See C++20 feature testing:
// https://en.cppreference.com/w/cpp/feature_test
#ifndef __has_feature #ifndef __has_feature
#define __has_feature(x) 0 // Compatibility with non-clang compilers. #define __has_feature(x) 0 // Compatibility with non-clang compilers.
#endif #endif
@ -316,6 +318,10 @@ using std::max;
#define __has_warning(x) 0 // Compatibility with non-clang compilers. #define __has_warning(x) 0 // Compatibility with non-clang compilers.
#endif #endif
#if __has_include(<version>)
# include <version>
#endif
// Macro to specify a 'unused' attribute. // Macro to specify a 'unused' attribute.
#if __has_cpp_attribute(maybe_unused) #if __has_cpp_attribute(maybe_unused)
# define CGAL_UNUSED [[maybe_unused]] # define CGAL_UNUSED [[maybe_unused]]

View File

@ -1166,6 +1166,24 @@ public:
} }
}; };
struct With_point_tag {};
template <class DSC, bool Const>
struct Output_rep<CGAL::internal::CC_iterator<DSC, Const>, With_point_tag>
: public Output_rep<CGAL::internal::CC_iterator<DSC, Const>>
{
using Base = Output_rep<CGAL::internal::CC_iterator<DSC, Const>>;
using Base::Base;
std::ostream& operator()(std::ostream& out) const {
Base::operator()(out);
if(this->it.operator->() != nullptr)
return out << "= " << this->it->point();
else
return out;
}
};
} //namespace CGAL } //namespace CGAL
namespace std { namespace std {

View File

@ -69,7 +69,10 @@ struct Time_stamper
static auto display_id(const T* pt) static auto display_id(const T* pt)
{ {
return std::string("#") + std::to_string(pt->time_stamp()); if(pt == nullptr)
return std::string("nullptr");
else
return std::string("#") + std::to_string(pt->time_stamp());
} }
static std::size_t hash_value(const T* p) { static std::size_t hash_value(const T* p) {

View File

@ -990,6 +990,52 @@ inline void read_float_or_quotient(std::istream& is, Rat &z)
} // namespace CGAL } // namespace CGAL
#if __has_include(<format>) && \
(__cpp_lib_format >= 201907L || __cplusplus >= 202000L || _MSVC_LANG >= 202000L)
# include <format>
# include <sstream>
namespace std {
template <typename T, typename F, typename CharT>
struct formatter<CGAL::Output_rep<T, F>, CharT> : public std::formatter<std::basic_string<CharT>>
{
constexpr auto parse(std::basic_format_parse_context<CharT>& ctx)
{
auto it = ctx.begin();
const auto end = ctx.end();
if(it == end)
return it;
if(*it != CharT('.'))
return it;
if(++it == end)
throw std::format_error("Missing precision");
if(*it < CharT('0') || *it > CharT('9'))
throw std::format_error("Invalid value for precision");
precision = *it - CharT('0');
while(++it != end) {
if(*it < CharT('0') || *it > CharT('9'))
return it;
precision = precision * 10 + (*it - CharT('0'));
}
return it;
}
template <typename FormatContext>
auto format(const CGAL::Output_rep<T, F> &rep, FormatContext& ctx) const
{
std::basic_stringstream<CharT> ss;
ss.precision(precision);
ss << rep;
return std::formatter<std::basic_string<CharT>>::format(ss.str(), ctx);
}
int precision = 17;
};
} // namespace std
#endif // __cpp_lib_format >= 201907L
#include <CGAL/enable_warnings.h> #include <CGAL/enable_warnings.h>
#endif // CGAL_IO_H #endif // CGAL_IO_H

View File

@ -37,28 +37,6 @@
#include <boost/mpl/has_xxx.hpp> #include <boost/mpl/has_xxx.hpp>
#include <boost/iterator/filter_iterator.hpp> #include <boost/iterator/filter_iterator.hpp>
#ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS
# include <CGAL/IO/io.h>
# include <CGAL/Compact_container.h>
# include <iostream>
namespace CGAL {
struct With_point_tag {};
template <class DSC, bool Const>
struct Output_rep<CGAL::internal::CC_iterator<DSC, Const>, With_point_tag>
: public Output_rep<CGAL::internal::CC_iterator<DSC, Const>>
{
using Base = Output_rep<CGAL::internal::CC_iterator<DSC, Const>>;
using Base::Base;
std::ostream& operator()(std::ostream& out) const {
return Base::operator()(out) << "= " << this->it->point();
}
};
} // namespace CGAL
#endif // CGAL_CDT_2_DEBUG_INTERSECTIONS
namespace CGAL { namespace CGAL {
struct No_constraint_intersection_tag{}; struct No_constraint_intersection_tag{};