Enable clang-tidy for headers
[alexxy/gromacs.git] / src / gromacs / utility / classhelpers.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2012,2013,2014,2015,2016,2018, 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 /*! \file
36  * \brief
37  * Declares common utility classes and macros.
38  *
39  * This header contains helpers used to implement classes in the library.
40  * It is installed, because the helpers are used in installed headers, but
41  * typically users of the library should not need to be aware of these helpers.
42  *
43  * \author Teemu Murtola <teemu.murtola@gmail.com>
44  * \inlibraryapi
45  * \ingroup module_utility
46  */
47 #ifndef GMX_UTILITY_CLASSHELPERS_H
48 #define GMX_UTILITY_CLASSHELPERS_H
49
50 #include <memory>
51
52 namespace gmx
53 {
54
55 #ifdef DOXYGEN
56 /*! \brief
57  * Macro to declare a class non-copyable and non-assignable.
58  *
59  * For consistency, should appear last in the class declaration.
60  *
61  * \ingroup module_utility
62  */
63 #define GMX_DISALLOW_COPY_AND_ASSIGN(ClassName)
64 #else
65 #define GMX_DISALLOW_COPY_AND_ASSIGN(ClassName) \
66     ClassName &operator=(const ClassName &) = delete;   \
67     ClassName(const ClassName &)            = delete
68 #endif
69 /*! \brief
70  * Macro to declare a class non-assignable.
71  *
72  * For consistency, should appear last in the class declaration.
73  *
74  * \ingroup module_utility
75  */
76 #define GMX_DISALLOW_ASSIGN(ClassName) \
77     ClassName &operator=(const ClassName &) = delete
78
79 #ifdef DOXYGEN
80 /*! \brief
81  * Macro to declare default constructors
82  *
83  * Intended for copyable interfaces or bases classes which require to create custom
84  * destructor (e.g. protected or virtual) but need the default constructors.
85  *
86  * \ingroup module_utility
87  */
88 #define GMX_DEFAULT_CONSTRUCTORS(ClassName)
89 #else
90 #define GMX_DEFAULT_CONSTRUCTORS(ClassName) \
91     ClassName()                                             = default;    \
92     ClassName                 &operator=(const ClassName &) = default; /* NOLINT(misc-macro-parentheses) */ \
93     ClassName(const ClassName &)                            = default;    \
94     ClassName                 &operator=(ClassName &&)      = default; /* NOLINT(misc-macro-parentheses) */ \
95     ClassName(ClassName &&)                                 = default  /* NOLINT(misc-macro-parentheses) */
96 #endif
97
98 /*! \brief
99  * Helper class to manage a pointer to a private implementation class.
100  *
101  * This helper provides the following benefits (all but the last could also be
102  * achieved with std::unique_ptr):
103  *  - Automatic memory management: the implementation pointer is freed in
104  *    the destructor automatically.  If the destructor is not declared or is
105  *    defined inline in the header file, a compilation error occurs instead
106  *    of a memory leak or undefined behavior.
107  *  - Exception safety in constructors: the implementation pointer is freed
108  *    correctly even if the constructor of the containing class throws after
109  *    the implementation class is constructed.
110  *  - Copy and/or assignment is automatically disallowed if explicit copy
111  *    constructor and/or assignment operator is not provided.
112  *  - Compiler helps to manage const-correctness: in const methods, it is not
113  *    possible to change the implementation class.
114  *
115  * Move construction and assignment are also disallowed, but can be enabled by
116  * providing explicit move constructor and/or assignment.
117  *
118  * Intended use:
119  * \code
120    // In exampleclass.h
121    class ExampleClass
122    {
123        public:
124            ExampleClass();
125            ~ExampleClass(); // Must be defined, must not be defined inline
126
127            // <...>
128
129        private:
130            class Impl;
131
132            PrivateImplPointer<Impl> impl_;
133    };
134
135    // In exampleclass.cpp
136
137    // <definition of ExampleClass::Impl>
138
139    ExampleClass::ExampleClass()
140        : impl_(new Impl)
141    {
142    }
143
144    ExampleClass::~ExampleClass()
145    {
146    }
147    \endcode
148  *
149  * Note that ExampleClass::~ExampleClass cannot be declared inline (or
150  * generated by the compiler) because the implementation of impl_
151  * requires that ExampleClass::Impl be known in size, whereas it has
152  * only been forward declared. Only the translation unit where
153  * ExampleClass::Impl is declared can define the destructor for
154  * ExampleClass (which may be defaulted).
155  *
156  * \inlibraryapi
157  * \ingroup module_utility
158  */
159 template <class Impl>
160 class PrivateImplPointer
161 {
162     public:
163         //! Allow implicit initialization from nullptr to support comparison.
164         PrivateImplPointer(std::nullptr_t) : ptr_(nullptr) {}
165         //! Initialize with the given implementation class.
166         explicit PrivateImplPointer(Impl *ptr) : ptr_(ptr) {}
167         //! \cond
168         // Explicitly declared to work around MSVC problems.
169         PrivateImplPointer(PrivateImplPointer &&other) noexcept : ptr_(std::move(other.ptr_)) {}
170         PrivateImplPointer &operator=(PrivateImplPointer &&other) noexcept
171         {
172             ptr_ = std::move(other.ptr_);
173             return *this;
174         }
175         //! \endcond
176
177         /*! \brief
178          * Sets a new implementation class and destructs the previous one.
179          *
180          * Needed, e.g., to implement lazily initializable or copy-assignable
181          * classes.
182          */
183         void reset(Impl *ptr) { ptr_.reset(ptr); }
184         //! Access the raw pointer.
185         Impl *get() { return ptr_.get(); }
186         //! Access the implementation class as with a raw pointer.
187         Impl *operator->() { return ptr_.get(); }
188         //! Access the implementation class as with a raw pointer.
189         Impl &operator*() { return *ptr_; }
190         //! Access the implementation class as with a raw pointer.
191         const Impl *operator->() const { return ptr_.get(); }
192         //! Access the implementation class as with a raw pointer.
193         const Impl &operator*() const { return *ptr_; }
194
195         //! Allows testing whether the implementation is initialized.
196         explicit operator bool() const { return ptr_ != nullptr; }
197
198         //! Tests for equality (mainly useful against nullptr).
199         bool operator==(const PrivateImplPointer &other) const { return ptr_ == other.ptr_; }
200         //! Tests for inequality (mainly useful against nullptr).
201         bool operator!=(const PrivateImplPointer &other) const { return ptr_ != other.ptr_; }
202
203     private:
204         std::unique_ptr<Impl> ptr_;
205
206         // Copy construction and assignment disabled by the unique_ptr member.
207 };
208
209 } // namespace gmx
210
211 #endif