2 * The Type2Type template and the Inheritance Detector are from
3 * <http://www.cuj.com/experts/1810/alexandr.htm>
4 * (c) Andrei Alexandrescu <andrei@metalanguage.com> and
8 * Copyright (C) 2001 Simon Hausmann <hausmann@kde.org>
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
20 * You should have received a copy of the GNU Library General Public License
21 * along with this library; see the file COPYING.LIB. If not, write to
22 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 * Boston, MA 02110-1301, USA.
30 // This file is not part of the KDE API. It exists for the convenience
31 // of KGenericFactory. This header file may change from version to
32 // version without notice, or even be removed.
37 #ifndef KGENERICFACTORY_TCC
38 #define KGENERICFACTORY_TCC
40 #include <QtCore/QMetaObject>
41 #include <ktypelist.h>
52 struct InheritanceDetector
54 typedef char ConversionExists;
55 struct ConversionDoesNotExist { char bleh[ 2 ]; };
56 static ConversionExists test( Base * );
57 static ConversionDoesNotExist test( ... );
60 /* Simon: KCC doesn't eat the generic InheritanceDetector<Base>.
61 Instead we have to use concrete specializations :-(
63 template <class Base, class Derived>
64 struct InheritanceTest
66 typedef Derived * DerivedPtr;
67 enum { Result = sizeof( InheritanceDetector<Base>::test( DerivedPtr() ) ) ==
68 sizeof( InheritanceDetector<Base>::ConversionExists ) };
72 template <class Derived>
73 struct QWidgetInheritanceTest
75 typedef Derived * DerivedPtr;
76 enum { Result = sizeof( InheritanceDetector<QWidget>::test( DerivedPtr() ) ) ==
77 sizeof( InheritanceDetector<QWidget>::ConversionExists ) };
80 template <class Derived>
81 struct PartInheritanceTest
83 typedef Derived * DerivedPtr;
84 enum { Result = sizeof( InheritanceDetector<KParts::Part>::test( DerivedPtr() ) ) ==
85 sizeof( InheritanceDetector<KParts::Part>::ConversionExists ) };
89 template <bool condition, typename Then, typename Else>
95 template <typename Then, typename Else>
96 struct If<true, Then, Else>
101 // a small helper template, to ease the overloading done in ConcreteFactory
102 // to choose the right constructor for the given class.
106 typedef T OriginalType;
110 // this template is called from the MultiFactory one. It instantiates
111 // the given class if the className matches. Instantiating is done by
112 // calling the right constructor (a parentwidget/parent
113 // one for Parts, a parentwidget one for widgets and last
114 // but not least the standard default constructor with a parent .
115 // the choice of the right constructor is done using an ordered inheritance
117 template <class Product, class ParentType = QObject>
118 class ConcreteFactory
121 typedef typename If< PartInheritanceTest< Product >::Result,
123 typename If< QWidgetInheritanceTest< Product >::Result,
124 QWidget, QObject >::Result >::Result BaseType;
126 static inline Product *create( QWidget *parentWidget,
128 const char *className, const QStringList &args )
130 const QMetaObject* metaObject = &Product::staticMetaObject;
133 //kDebug(150) << "className=" << className << " metaObject->className()=" << metaObject->className() << endl;
134 if ( !qstrcmp( className, metaObject->className() ) )
135 return create( parentWidget,
136 parent, args, Type2Type<BaseType>() );
137 metaObject = metaObject->superClass();
139 //kDebug(150) << "error, returning 0" << endl;
143 typedef typename If< QWidgetInheritanceTest<ParentType>::Result,
144 ParentType, QWidget >::Result WidgetParentType;
146 static inline Product *create( QWidget *parentWidget,
148 const QStringList &args, Type2Type<KParts::Part> )
150 //kDebug(150) << "create - 1" << endl;
151 return new Product( parentWidget, parent, args );
154 static inline Product *create( QWidget* /*parentWidget*/,
156 const QStringList &args, Type2Type<QWidget> )
158 //kDebug(150) << "create - 2" << endl;
159 WidgetParentType *p = dynamic_cast<WidgetParentType *>( parent );
162 return new Product( p, args );
165 static inline Product *create( QWidget* /*parentWidget*/,
167 const QStringList &args, Type2Type<QObject> )
169 //kDebug(150) << "create - 3" << endl;
170 ParentType *p = dynamic_cast<ParentType *>( parent );
173 return new Product( p, args );
177 // this template is used to iterate through the typelist and call the
178 // concrete factory for each type. the specializations of this template
179 // are the ones actually being responsible for iterating, in fact.
180 template <class Product, class ParentType = QObject>
184 inline static QObject *create( QWidget *parentWidget,
186 const char *className,
187 const QStringList &args )
189 return ConcreteFactory<Product, ParentType>::create( parentWidget,
196 // this specialized template we 'reach' at the end of a typelist
197 // (the last item in a typelist is the NullType)
199 class MultiFactory<KDE::NullType>
202 inline static QObject *create( QWidget *, QObject *,
204 const QStringList & )
208 // this specialized template we 'reach' at the end of a typelist
209 // (the last item in a typelist is the NullType)
211 class MultiFactory<KDE::NullType, KDE::NullType>
214 inline static QObject *create( QWidget *, QObject *,
216 const QStringList & )
220 template <class Product, class ProductListTail>
221 class MultiFactory< KTypeList<Product, ProductListTail>, QObject >
224 inline static QObject *create( QWidget *parentWidget,
226 const char *className,
227 const QStringList &args )
229 // try with the head of the typelist first. the head is always
231 QObject *object = MultiFactory<Product>::create( parentWidget,
236 object = MultiFactory<ProductListTail>::create( parentWidget,
244 template <class Product, class ProductListTail,
245 class ParentType, class ParentTypeListTail>
246 class MultiFactory< KTypeList<Product, ProductListTail>,
247 KTypeList<ParentType, ParentTypeListTail> >
250 inline static QObject *create( QWidget *parentWidget,
252 const char *className,
253 const QStringList &args )
255 // try with the head of the typelist first. the head is always
257 QObject *object = MultiFactory<Product, ParentType>
258 ::create( parentWidget,
259 parent, className, args );
261 // if that failed continue by advancing the typelist, calling this
262 // template specialization recursively (with T2 being a typelist) .
263 // at the end we reach the nulltype specialization.
265 object = MultiFactory<ProductListTail, ParentTypeListTail>
266 ::create( parentWidget,
267 parent, className, args );