From 93fcfa58fec6c78960ecc3434c1c57554e6577ea Mon Sep 17 00:00:00 2001 From: Luca Heltai Date: Thu, 20 Jul 2017 12:18:51 +0200 Subject: [PATCH] Support for std::pair --- include/deal.II/base/pattern_tools.h | 82 +++++++++++++++++++++++++--- tests/base/pattern_tools_02.cc | 2 + tests/base/pattern_tools_02.output | 3 + 3 files changed, 78 insertions(+), 9 deletions(-) diff --git a/include/deal.II/base/pattern_tools.h b/include/deal.II/base/pattern_tools.h index fccce279cf..80945534a7 100644 --- a/include/deal.II/base/pattern_tools.h +++ b/include/deal.II/base/pattern_tools.h @@ -128,6 +128,8 @@ namespace PatternTools * The second template parameter is used internally to allow for advanced * SFINAE (substitution failure is not an error) tricks used to specialise * this class for arbitrary STL containers and maps. + * + * @author Luca Heltai, 2017 */ template struct Convert @@ -136,6 +138,10 @@ namespace PatternTools /** * Return a std::unique_ptr to a Pattern that can be used to interpret a * string as the type of the template argument, and the other way around. + * + * While the current function (in the general Convert template) is deleted, + * it is implemented and available in the specializations of the Convert + * class template for particular kinds of template arguments @p T. */ static std::unique_ptr to_pattern() = delete; @@ -144,7 +150,9 @@ namespace PatternTools * pattern passed to perform the conversion, or create and use a default * one. * - * The created string is + * While the current function (in the general Convert template) is deleted, + * it is implemented and available in the specializations of the Convert + * class template for particular kinds of template arguments @p T. */ static std::string to_string(const T &s, const std::unique_ptr @@ -153,6 +161,10 @@ namespace PatternTools /** * Convert a string to a value, using the given pattern. Use the pattern * passed to perform the conversion, or create and use a default one. + * + * While the current function (in the general Convert template) is deleted, + * it is implemented and available in the specializations of the Convert + * class template for particular kinds of template arguments @p T. */ static T to_value(const std::string &s, const std::unique_ptr &p = @@ -217,10 +229,10 @@ namespace PatternTools * map. A class with map_rank::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. + * 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. * * @author Luca Heltai, 2017 */ @@ -275,6 +287,13 @@ namespace PatternTools } else is >> value; + + // If someone passes "123 abc" to the function, the method yelds an + // integer 123 alright, but the space terminates the read from the string + // although there is more to come. This case, however, is checked for in + // the call p->match(s) at the beginning of this function, and would + // throw earlier. Here it is safe to assume that if we didn't fail the + // conversion with the operator >>, then we are good to go. AssertThrow(!is.fail(), ExcMessage("Failed to convert from \"" + s + "\" to the type \"" + @@ -368,6 +387,13 @@ namespace PatternTools static constexpr int list_rank = RankInfo::list_rank + 1; static constexpr int map_rank = RankInfo::map_rank; }; + + template + struct RankInfo> + { + static constexpr int list_rank = std::max(RankInfo::list_rank, RankInfo::list_rank); + static constexpr int map_rank = std::max(RankInfo::map_rank, RankInfo::map_rank)+1; + }; } // stl containers @@ -412,9 +438,6 @@ namespace PatternTools return s; } - /** - * Convert a string to a value, using the given pattern, or a default one. - */ static T to_value(const std::string &s, const std::unique_ptr &pattern = Convert::to_pattern()) @@ -463,7 +486,6 @@ namespace PatternTools const std::unique_ptr &pattern = Convert::to_pattern()) { - auto p = dynamic_cast(pattern.get()); AssertThrow( p, @@ -706,6 +728,48 @@ namespace PatternTools } }; + + // Pairs + template + struct Convert> + { + typedef std::pair T; + + static std::unique_ptr to_pattern() + { + static_assert(internal::RankInfo::map_rank > 0, + "Cannot use this class for non Map-compatible types."); + return std_cxx14::make_unique( + *Convert::to_pattern(), + *Convert::to_pattern(), + 1, 1, + // We keep the same list separator of the previous level, as this is + // a map with only 1 possible entry + internal::default_list_separator[internal::RankInfo::list_rank], + internal::default_map_separator[internal::RankInfo::map_rank - 1]); + } + + static std::string to_string(const T &t, + const std::unique_ptr + &pattern = Convert::to_pattern()) + { + std::unordered_map m; + m.insert(t); + std:: string s = Convert::to_string(m, pattern); + AssertThrow(pattern->match(s), ExcNoMatch(s, *pattern)); + return s; + } + + static T to_value(const std::string &s, + const std::unique_ptr &pattern = + Convert::to_pattern()) + { + std::unordered_map m; + m = Convert::to_value(s, pattern); + return *m.begin(); + } + }; + template void add_parameter(const std::string &entry, ParameterType ¶meter, diff --git a/tests/base/pattern_tools_02.cc b/tests/base/pattern_tools_02.cc index 00f015fce2..4c9ee96621 100644 --- a/tests/base/pattern_tools_02.cc +++ b/tests/base/pattern_tools_02.cc @@ -60,6 +60,7 @@ int main() Tensor<3,3> t53; std::complex t6(1,2); + auto t7 = std::make_pair(1, 2.0); test(t0); test(t1); @@ -68,6 +69,7 @@ int main() test(t4); test(t5); test(t6); + test(t7); test(t32); test(t42); test(t52); diff --git a/tests/base/pattern_tools_02.output b/tests/base/pattern_tools_02.output index be28c44a36..1db60afdd5 100644 --- a/tests/base/pattern_tools_02.output +++ b/tests/base/pattern_tools_02.output @@ -20,6 +20,9 @@ DEAL::To value : 0.000000, 0.000000, 0.000000 DEAL::Pattern : [List of <[Double -MAX_DOUBLE...MAX_DOUBLE (inclusive)]> of length 2...2 (inclusive)] DEAL::To String: 1.000000, 2.000000 DEAL::To value : 1.000000, 2.000000 +DEAL::Pattern : [Map of <[Integer range -2147483648...2147483647 (inclusive)]>:<[Double -MAX_DOUBLE...MAX_DOUBLE (inclusive)]> of length 1...1 (inclusive)] +DEAL::To String: 1:2.000000 +DEAL::To value : 1:2.000000 DEAL::Pattern : [List of <[List of <[Double -MAX_DOUBLE...MAX_DOUBLE (inclusive)]> of length 1...1 (inclusive)]> of length 1...1 (inclusive) separated by <;>] DEAL::To String: 0.000000 DEAL::To value : 0.000000 -- 2.39.5