LUMIERA.clone/research/clang-static-init.hpp
Ichthyostega cdb3d3045a BUG: Clang shows a problem when accessing templated static variable through separate compilation units
this is really creepy: the same(!) instance of the singleton factory
sees different addresses of the class static variable, depending on
the compilation unit.

Please note that the type of the concrete factory function is *erased*
when exiting the constructor function of ConfigurableHolder
2013-10-06 23:17:18 +02:00

140 lines
2.7 KiB
C++

#include <iostream>
using std::cout;
namespace test {
/* === Layer-1: a singleton factory based on a templated static variable === */
template<typename I ///< Interface of the product type
,template <class> class Fac ///< Policy: actual factory to create the instance
>
struct Holder
{
static I* instance;
I&
get()
{
if (!instance)
{
cout << "Singleton Factory: invoke Fabrication ---> address of static instance variable: "<<&instance<<"...\n";
instance = Fac<I>::create();
}
return *instance;
}
};
/**
* allocate storage for the per-type shared
* (static) variable to hold the singleton instance
*/
template<typename I
,template <class> class F
>
I* Holder<I,F>::instance;
template<typename C>
struct Factory
{
static C*
create()
{
return new C();
}
};
/* === Layer-2: configurable product type === */
template<typename I>
struct Adapter
{
typedef I* FactoryFunction (void);
static FactoryFunction* factoryFunction;
template<typename C>
static I*
concreteFactoryFunction()
{
return static_cast<I*> (Factory<C>::create());
}
template<typename X>
struct AdaptedConfigurableFactory
{
static X*
create()
{
return (*factoryFunction)();
}
};
};
/** storage for the per-type shared function pointer to the concrete factory */
template<typename I>
typename Adapter<I>::FactoryFunction* Adapter<I>::factoryFunction;
template<typename C>
struct TypeInfo { };
/**
* Singleton factory with the ability to configure the actual product type C
* only at the \em definition site. Users get to see only the interface type T
*/
template<typename T>
struct ConfigurableHolder
: Holder<T, Adapter<T>::template AdaptedConfigurableFactory>
{
/** define the actual product type */
template<typename C>
ConfigurableHolder (TypeInfo<C>)
{
Adapter<T>::factoryFunction = &Adapter<T>::template concreteFactoryFunction<C>;
}
};
/* === Actual usage: Test case fabricating Subject instances === */
struct Subject
{
static int creationCount;
Subject();
};
typedef ConfigurableHolder<Subject> AccessPoint;
extern AccessPoint fab;
Subject& fabricate();
} // namespace test