GROMACS: src/gromacs/utility/any.h | Fossies




GROMACS: src/gromacs/utility/any.h | Fossies


Fossies” – the Fresh Open Source Software Archive

Member “gromacs-2021.3/src/gromacs/utility/any.h” (18 Aug 2021, 8080 Bytes) of package /linux/privat/gromacs-2021.3.tar.gz:


As a special service “Fossies” has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option.
Alternatively you can here view or download the uninterpreted source code file.
For more information about “any.h” see the Fossies “Dox” file reference documentation and the last Fossies “Diffs” side-by-side code changes report: 2020.5_vs_2021.

    1 /*
    2  * This file is part of the GROMACS molecular simulation package.
    3  *
    4  * Copyright (c) 2016,2017,2018,2019,2020, 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  * Declares gmx::Any.
   38  *
   39  * author Teemu Murtola <teemu.murtola@gmail.com>
   40  * inlibraryapi
   41  * ingroup module_utility
   42  */
   43 #ifndef GMX_UTILITY_ANY_H
   44 #define GMX_UTILITY_ANY_H
   45 
   46 #include <memory>
   47 #include <string>
   48 #include <type_traits>
   49 #include <typeindex>
   50 #include <typeinfo>
   51 #include <utility>
   52 
   53 #include "gromacs/utility/gmxassert.h"
   54 
   55 namespace gmx
   56 {
   57 
   58 /*! libinternal brief
   59  * Represents a dynamically typed value of an arbitrary type.
   60  *
   61  * To create a any, either initialize it as empty, or with the create()
   62  * method (or the equivalent constructor, if the type parameter can be deduced
   63  * and is clear to the reader from the context).
   64  *
   65  * To query the type of the contents in the any, use isEmpty(), type(), and
   66  * isType().
   67  *
   68  * To access the value, you need to know the type as a compile-time constant
   69  * (e.g., through branching based on isType()), and then use cast() or
   70  * tryCast().
   71  *
   72  * Methods in this class do not throw unless otherwise indicated.
   73  *
   74  * This provides essentially the same functionality as boost::any.
   75  *
   76  * ingroup module_utility
   77  */
   78 class Any
   79 {
   80 public:
   81     /*! brief
   82      * Creates a any that holds the given value.
   83      *
   84      * throws std::bad_alloc if out of memory.
   85      *
   86      * This method allows explicitly specifying the template argument,
   87      * contrary to the templated constructor.
   88      */
   89     template<typename T>
   90     static Any create(const T& value)
   91     {
   92         return Any(value);
   93     }
   94     /*! brief
   95      * Creates a any that holds the given value.
   96      *
   97      * throws std::bad_alloc if out of memory.
   98      *
   99      * In addition to allowing specifying the template argument, this
  100      * method avoids copying when move-construction is possible.
  101      */
  102     template<typename T>
  103     static Any create(T&& value)
  104     {
  105         return Any(std::forward<T>(value));
  106     }
  107 
  108     //! Creates an empty any value.
  109     Any() {}
  110     /*! brief
  111      * Creates a any that holds the given value.
  112      *
  113      * throws std::bad_alloc if out of memory.
  114      */
  115     template<typename T, typename = std::enable_if_t<!std::is_same<T, Any>::value>>
  116     explicit Any(T&& value) :
  117         content_(new Content<typename std::decay<T>::type>(std::forward<T>(value)))
  118     {
  119     }
  120     /*! brief
  121      * Creates a deep copy of a any.
  122      *
  123      * throws std::bad_alloc if out of memory.
  124      */
  125     Any(const Any& other) : content_(other.cloneContent()) {}
  126     //! Move-constructs a any.
  127     Any(Any&& other) noexcept : content_(std::move(other.content_)) {}
  128     /*! brief
  129      * Assigns the any.
  130      *
  131      * throws std::bad_alloc if out of memory.
  132      */
  133     Any& operator=(const Any& other)
  134     {
  135         content_ = other.cloneContent();
  136         return *this;
  137     }
  138     //! Move-assigns the any.
  139     Any& operator=(Any&& other) noexcept
  140     {
  141         content_ = std::move(other.content_);
  142         return *this;
  143     }
  144 
  145     //! Whether any value is stored.
  146     bool isEmpty() const { return content_ == nullptr; }
  147     //! Returns the dynamic type of the value that is currently stored.
  148     std::type_index type() const
  149     {
  150         const std::type_info& info = !isEmpty() ? content_->typeInfo() : typeid(void);
  151         return std::type_index(info);
  152     }
  153     //! Returns whether the type stored matches the template parameter.
  154     template<typename T>
  155     bool isType() const
  156     {
  157         return !isEmpty() && content_->typeInfo() == typeid(T);
  158     }
  159 
  160     /*! brief
  161      * Tries to get the value as the given type.
  162      *
  163      * tparam T  Type to get.
  164      * returns Pointer to the value, or nullptr if the type does not match
  165      *     the stored value.
  166      */
  167     template<typename T>
  168     const T* tryCast() const
  169     {
  170         return isType<T>() ? &static_cast<Content<T>*>(content_.get())->value_ : nullptr;
  171     }
  172     /*! brief
  173      * Gets the value when the type is known.
  174      *
  175      * tparam T  Type to get (which must match what the any stores).
  176      *
  177      * Asserts if the any is empty or does not contain the requested type.
  178      */
  179     template<typename T>
  180     const T& cast() const
  181     {
  182         const T* value = tryCast<T>();
  183         GMX_RELEASE_ASSERT(value != nullptr, "Cast to incorrect type");
  184         return *value;
  185     }
  186     /*! brief
  187      * Tries to get the value as the given type as a non-const pointer.
  188      *
  189      * tparam T  Type to get.
  190      * returns Pointer to the value, or nullptr if the type does not match
  191      *     the stored value.
  192      *
  193      * This method allows modifying the value in-place, which is useful
  194      * with more complicated data structures.
  195      */
  196     template<typename T>
  197     T* tryCastRef()
  198     {
  199         return isType<T>() ? &static_cast<Content<T>*>(content_.get())->value_ : nullptr;
  200     }
  201     /*! brief
  202      * Gets the value when the type is known as a modifiable reference.
  203      *
  204      * tparam T  Type to get (which must match what the any stores).
  205      *
  206      * Asserts if the any is empty or does not contain the requested type.
  207      */
  208     template<typename T>
  209     T& castRef()
  210     {
  211         T* value = tryCastRef<T>();
  212         GMX_RELEASE_ASSERT(value != nullptr, "Cast to incorrect type");
  213         return *value;
  214     }
  215 
  216 private:
  217     class IContent
  218     {
  219     public:
  220         virtual ~IContent() {}
  221         virtual const std::type_info&     typeInfo() const = 0;
  222         virtual std::unique_ptr<IContent> clone() const    = 0;
  223     };
  224 
  225     template<typename T>
  226     class Content : public IContent
  227     {
  228     public:
  229         explicit Content(const T& value) : value_(value) {}
  230         explicit Content(T&& value) : value_(std::move(value)) {}
  231 
  232         const std::type_info&     typeInfo() const override { return typeid(T); }
  233         std::unique_ptr<IContent> clone() const override
  234         {
  235             return std::make_unique<Content>(value_);
  236         }
  237 
  238         T value_;
  239     };
  240 
  241     //! Creates a deep copy of the content.
  242     std::unique_ptr<IContent> cloneContent() const
  243     {
  244         return content_ != nullptr ? content_->clone() : nullptr;
  245     }
  246 
  247     std::unique_ptr<IContent> content_;
  248 };
  249 
  250 //! cond libapi
  251 /*! brief
  252  * Converts a Any value to a string.
  253  *
  254  * As the name suggests, only some types of "simple" values (such as int) are
  255  * supported.  Asserts for unsupported types.
  256  *
  257  * ingroup module_utility
  258  */
  259 std::string simpleValueToString(const Any& value);
  260 //! endcond
  261 
  262 } // namespace gmx
  263 
  264 #endif

Read more here: Source link