From 35f3538c06a8d45172bdda5d49e40c178ae5362c Mon Sep 17 00:00:00 2001 From: Luca Heltai Date: Tue, 18 Jul 2017 20:15:12 +0200 Subject: [PATCH] Patterns for arithmetic types and container types. --- include/deal.II/base/patterns_tools.h | 152 +++++++++++++++++++++++++- source/base/patterns_tools.cc | 2 +- 2 files changed, 148 insertions(+), 6 deletions(-) diff --git a/include/deal.II/base/patterns_tools.h b/include/deal.II/base/patterns_tools.h index cc4bb028a1..92549022b9 100644 --- a/include/deal.II/base/patterns_tools.h +++ b/include/deal.II/base/patterns_tools.h @@ -45,6 +45,55 @@ DEAL_II_NAMESPACE_OPEN namespace PatternsTools { using namespace Patterns; + + + /** + * Store information about the rank types of the given class. + * + * A class has Rank equal to the number of different separators + * that are required to specify its element(s) in a string. + * + * This class is used to detect wether the class T is compatible + * with a Patterns::List pattern or with a Patterns::Map pattern, and + * to choose among a default list of separators for complex types, + * like vectors of vectors. + * + * Objects like Point or std::complex are vector-likes, and + * have vector_rank 1. Elementary types, like `int`, `unsigned int`, `double`, etc. + * have vector_rank 0. `std::vector`, `std::list` and in general containers have rank + * equal to 1 + vector_rank of the contained type. Similarly for map types. + * + * A class with vector_rank_type::value = 0 is either elementary or a + * map. A class with map_rank_type::value = 0 is either a List compatible + * class, or an elementary type. + * + * Elementary types are not compatible with Patterns::List, but + * non elementary types, like Point(), or std::complex, are + * compatible with the List type. Adding more compatible types is a matter + * of adding a specialization of this struct for the given type. + */ + template + struct RankInfo + { + typedef std::integral_constant::type vector_rank_type; + }; + + + /** + * Return the default list separator for an object with the given vector rank. + * + * Objects like Point or std::complex are vector-likes, and + * have rank 1. Elementary types, like `int`, `unsigned int`, `double`, etc. + * have rank 0. `std::vector`, `std::list` and in general containers have rank + * equal to 1 + rank of the contained type. + * + * This function helps in constructing patterns for non elementary types, + * like for example std::vector>>. + */ + std::string default_list_separator(unsigned int); + + + /** * Converter class. This class is used to generate strings and Patterns associated to * the given type, and to convert from a string to the given type and viceversa. @@ -75,6 +124,19 @@ namespace PatternsTools std::unique_ptr p = Convert::to_pattern()) = delete; }; + /** + * @addtogroup Exceptions + * @{ + */ + + /** + * Exception. + */ + DeclException2 (ExcNoMatch, + std::string, PatternBase &, + << "The string " << arg1 << " does not match the pattern \"" + << arg2.description() << "\""); + //@} } @@ -83,33 +145,113 @@ namespace PatternsTools namespace PatternsTools { template - struct Convert::value>::type> + struct Convert::value>::type> { static std::unique_ptr to_pattern() { - return std_cxx14::make_unique(std::numeric_limits::min(), std::numeric_limits::max()); + if(std::is_integral::value) + return std_cxx14::make_unique(std::numeric_limits::min(), std::numeric_limits::max()); + else if(std::is_floating_point::value) + return std_cxx14::make_unique(std::numeric_limits::min(), std::numeric_limits::max()); + else { + AssertThrow(false, ExcNotImplemented()); + return std::unique_ptr(); + } } static std::string to_string(const T &value, std::unique_ptr p = Convert::to_pattern()) { std::stringstream str; str << value; - AssertThrow(p->match(str.str()), ExcMessage("No match")); + AssertThrow(p->match(str.str()), ExcNoMatch(str.str(), *p)); return str.str(); } static T to_value(const std::string &s, std::unique_ptr p = Convert::to_pattern()) { - AssertThrow(p->match(s), ExcMessage("No match")); + AssertThrow(p->match(s), ExcNoMatch(s, *p)); std::istringstream is(s); T i; is >> i; - AssertThrow(!is.fail(), ExcMessage("Failed to convert")); + AssertThrow(!is.fail(), ExcMessage("Failed to convert from \"" + s + "\" to the type \"" + +boost::core::demangle(typeid(T).name()) + "\"")); return i; } }; + + // Rank of vector types + template