Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/libraries/core/class/SubclassIdentifier.h @ 12171

Last change on this file since 12171 was 11083, checked in by muemart, 9 years ago

Fix some clang-tidy warnings.
Also, Serialise.h was doing some C-style casts that ended up being const casts. I moved those const casts as close to the source as possible and changed the loadAndIncrease functions to not do that.

  • Property svn:eol-style set to native
File size: 8.0 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29/**
30    @file
31    @ingroup Class Identifier
32    @brief Definition of SubclassIdentifier.
33
34    @anchor SubclassIdentifierExample
35
36    SubclassIdentifier is a separated class, acting like an Identifier, but has a given class.
37    You can only assign Identifiers of exactly the given class or of a derivative to a SubclassIdentifier.
38
39    Example:
40
41    You can assign an Identifier either through the constructor or by using the assignment @c operator=:
42    @code
43    SubclassIdentifier<BaseClass> identifier = Class(SubClass);
44    @endcode
45
46    The @c operator-> is overloaded an returns the assigned Identifier. That way you can just call
47    functions of the assigned Identifier by using @c ->function():
48    @code
49    SubclassIdentifier<BaseClass> identifier = Class(SubClass);
50    identifier->getName();      // returns "SubClass"
51    @endcode
52
53    There are two possibilities to create an object out of a SubclassIdentifier: Either you just use
54    the @c fabricate() function of the assigned Identifier through the overloaded @c operator->, which
55    returns a @c OrxonoxClass* pointer, or you use the function of SubclassIdentifier, this time by using
56    @c operator., which returns a @c BaseClass* pointer (@a BaseClass is the baseclass specified by the
57    template argument):
58    @code
59    identifier->fabricate();    // calls Identifier::fabricate(), creates a SubClass, returns a OrxonoxClass* pointer
60
61    identifier.fabricate();     // calls SubclassIdentifier::fabricate(), creates a SubClass, returns a BaseClass* pointer
62    @endcode
63*/
64
65#ifndef _SubclassIdentifier_H__
66#define _SubclassIdentifier_H__
67
68#include "core/CorePrereqs.h"
69
70#include <cstdlib>
71#include "util/Output.h"
72#include "Identifier.h"
73
74namespace orxonox
75{
76    // ###############################
77    // ###   SubclassIdentifier    ###
78    // ###############################
79    /**
80        @brief The SubclassIdentifier acts almost like an Identifier, but has some prerequisites.
81
82        You can only assign an Identifier that belongs to a class T (or derived) to a SubclassIdentifier<T>.
83        If you assign something else, the program prints an error.
84
85        Because we know the base-type, a @c dynamic_cast is done, which makes it easier to create a new object.
86
87        @see See @ref SubclassIdentifierExample "SubclassIdentifier.h" for some examples.
88    */
89    template <class T>
90    class SubclassIdentifier
91    {
92        public:
93            /// Constructor: Automaticaly assigns the Identifier of the given class.
94            SubclassIdentifier() : identifier_(nullptr)
95            {
96                this->identifier_ = ClassIdentifier<T>::getIdentifier();
97            }
98
99            /// Constructor: Assigns the given Identifier.
100            SubclassIdentifier(Identifier* identifier) : identifier_(nullptr)
101            {
102                this->operator=(identifier);
103            }
104
105            /// Copyconstructor: Assigns the identifier of another SubclassIdentifier.
106            template <class O>
107            SubclassIdentifier(const SubclassIdentifier<O>& identifier) : identifier_(nullptr)
108            {
109                this->operator=(identifier.getIdentifier());
110            }
111
112            /**
113                @brief Overloading of the = operator: assigns the identifier and checks its type.
114                @param identifier The Identifier to assign
115                @return The SubclassIdentifier itself
116            */
117            SubclassIdentifier<T>& operator=(Identifier* identifier)
118            {
119                if (!identifier || !identifier->isA(ClassIdentifier<T>::getIdentifier()))
120                {
121                    orxout(internal_error) << "An error occurred in SubclassIdentifier (Identifier.h):" << endl;
122                    if (identifier)
123                    {
124                        orxout(internal_error) << "Class " << identifier->getName() << " is not a " << ClassIdentifier<T>::getIdentifier()->getName() << '!' << endl;
125                        orxout(internal_error) << "SubclassIdentifier<" << ClassIdentifier<T>::getIdentifier()->getName() << "> = Class(" << identifier->getName() << ") is forbidden." << endl;
126                    }
127                    else
128                    {
129                        orxout(internal_error) << "Can't assign nullptr identifier" << endl;
130                    }
131                }
132                else
133                {
134                    this->identifier_ = identifier;
135                }
136                return *this;
137            }
138
139            /// Overloading of the = operator: assigns the identifier of another SubclassIdentifier.
140            template <class O>
141            SubclassIdentifier<T>& operator=(const SubclassIdentifier<O>& identifier)
142            {
143                return this->operator=(identifier.getIdentifier());
144            }
145
146            /// Overloading of the * operator: returns the assigned identifier.
147            inline Identifier* operator*() const
148            {
149                return this->identifier_;
150            }
151
152            /// Overloading of the -> operator: returns the assigned identifier.
153            inline Identifier* operator->() const
154            {
155                return this->identifier_;
156            }
157
158            /// Returns the assigned identifier. This allows you to assign a SubclassIdentifier to a normal Identifier*.
159            inline operator Identifier*() const
160            {
161                return this->identifier_;
162            }
163
164            /// Creates a new object of the type of the assigned Identifier and dynamic_casts it to the minimal type given by T.
165            T* fabricate(Context* context) const
166            {
167                Identifiable* newObject = this->identifier_->fabricate(context);
168
169                // Check if the creation was successful
170                if (newObject)
171                {
172                    return orxonox_cast<T*>(newObject);
173                }
174                else
175                {
176                    // Something went terribly wrong
177                    if (this->identifier_)
178                    {
179                        orxout(user_error) << "An error occurred in SubclassIdentifier (Identifier.h):" << endl;
180                        orxout(user_error) << "Class " << this->identifier_->getName() << " is not a " << ClassIdentifier<T>::getIdentifier()->getName() << '!' << endl;
181                        orxout(user_error) << "Couldn't fabricate a new Object." << endl;
182                    }
183                    else
184                    {
185                        orxout(user_error) << "An error occurred in SubclassIdentifier (Identifier.h):" << endl;
186                        orxout(user_error) << "Couldn't fabricate a new Object - Identifier is undefined." << endl;
187                    }
188
189                    orxout(user_error) << "Aborting..." << endl;
190                    abort();
191                    return nullptr;
192                }
193            }
194
195            /// Returns the assigned identifier.
196            inline Identifier* getIdentifier() const
197                { return this->identifier_; }
198
199        private:
200            Identifier* identifier_;            //!< The assigned identifier
201    };
202}
203
204#endif /* _SubclassIdentifier_H__ */
Note: See TracBrowser for help on using the repository browser.