1 /* 2 * This file is part of the GROMACS molecular simulation package. 3 * 4 * Copyright (c) 2016,2019, by the GROMACS development team, led by 5 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl, 6 * and including many others, as listed in the AUTHORS file in the 7 * top-level source directory and at http://www.gromacs.org. 8 * 9 * GROMACS is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU Lesser General Public License 11 * as published by the Free Software Foundation; either version 2.1 12 * of the License, or (at your option) any later version. 13 * 14 * GROMACS is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * Lesser General Public License for more details. 18 * 19 * You should have received a copy of the GNU Lesser General Public 20 * License along with GROMACS; if not, see 21 * http://www.gnu.org/licenses, or write to the Free Software Foundation, 22 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23 * 24 * If you want to redistribute modifications to GROMACS, please 25 * consider that scientific software is very special. Version 26 * control is crucial - bugs must be traceable. We will be happy to 27 * consider code for inclusion in the official distribution, but 28 * derived work must not be called official GROMACS. Details are found 29 * in the README & COPYING files - if they are missing, get the 30 * official version at http://www.gromacs.org. 31 * 32 * To help us fund GROMACS development, we humbly ask that you cite 33 * the research papers on the package. Check out http://www.gromacs.org. 34 */ 35 /*! \libinternal \file 36 * \brief 37 * Provides gmx::OptionValueConverterSimple. 38 * 39 * \author Teemu Murtola <teemu.murtola@gmail.com> 40 * \ingroup module_options 41 */ 42 #ifndef GMX_OPTIONS_VALUECONVERTER_H 43 #define GMX_OPTIONS_VALUECONVERTER_H 44 45 #include <functional> 46 #include <map> 47 #include <typeindex> 48 49 #include "gromacs/utility/any.h" 50 #include "gromacs/utility/exceptions.h" 51 52 namespace gmx 53 { 54 55 /*! \libinternal \brief 56 * Helper for converting from Any to a given type. 57 * 58 * \tparam OutType Type this converter converts to. 59 * 60 * Default-constructed converter only supports identity mapping from the a 61 * Any holding `OutType`. To add support for additional input types, 62 * provide conversion functions with addConverter(). To use a non-identity 63 * mapping for an `OutType` -> `OutType` conversion, provide an alternative 64 * conversion from `OutType` with addConverter(). 65 * 66 * \inlibraryapi 67 * \ingroup module_options 68 */ 69 template<typename OutType> 70 class OptionValueConverterSimple 71 { 72 public: 73 /*! \brief 74 * Converts a Any value to the output type. 75 * 76 * \returns Converted value. 77 * \throws InvalidInputError If the input Any has a type that is 78 * not recognized by any conversion. 79 */ convert(const Any & value)80 OutType convert(const Any& value) const 81 { 82 std::type_index type(value.type()); 83 auto iter = converters_.find(type); 84 if (iter == converters_.end()) 85 { 86 if (value.isType<OutType>()) 87 { 88 return value.cast<OutType>(); 89 } 90 GMX_THROW(InvalidInputError("Invalid type of value")); 91 } 92 return iter->second(value); 93 } 94 95 /*! \brief 96 * Adds a supported conversion. 97 * 98 * \tparam InType Type to convert from. 99 * \param func Function to convert from `InType` to `OutType`. 100 */ 101 template<typename InType> addConverter(std::function<OutType (const InType &)> func)102 void addConverter(std::function<OutType(const InType&)> func) 103 { 104 converters_[std::type_index(typeid(InType))] = [func](const Any& value) { 105 return func(value.cast<InType>()); 106 }; 107 } 108 /*! \brief 109 * Adds a supported conversion from a type that can be directly cast. 110 * 111 * \tparam InType Type to convert from with a simple cast. 112 */ 113 template<typename InType> addCastConversion()114 void addCastConversion() 115 { 116 converters_[std::type_index(typeid(InType))] = [](const Any& value) { 117 return static_cast<OutType>(value.cast<InType>()); 118 }; 119 } 120 121 private: 122 typedef std::function<OutType(const Any& value)> ConversionFunction; 123 124 std::map<std::type_index, ConversionFunction> converters_; 125 }; 126 127 } // namespace gmx 128 129 #endif 130