//
//---- begin file library.h ----
//
#include <map>
#include <string>
#include <iostream>
typedef void(*policyFunction)();
typedef std::map<const void *, policyFunction> policyMap_t;
// singleton class to manage policies
class Policies {
public:
void registerInstance(const void * const v,
const policyFunction func);
policyFunction isRegistered(const void * const v) const;
void policy(const void * const v) const;
static Policies& instancePolicyMap();
private:
Policies() {}
policyMap_t instanceMap_;
};
// member function definitions
void
Policies::registerInstance(const void * const v,
const policyFunction func)
{
if(v != 0 && func != 0) {
instanceMap_[v] = func;
}
}
policyFunction
Policies::isRegistered(const void * const v) const
{
policyMap_t::const_iterator iter = instanceMap_.find(v);
if (iter != instanceMap_.end()) {
return (*iter).second;
}
else {
return 0;
}
}
void
Policies::policy(const void * const v) const
{
if (policyFunction pFunc = isRegistered(v)) {
pFunc();
}
}
Policies&
Policies::instancePolicyMap()
{
static Policies typeMap;
return typeMap;
}
// namespace scope function for convenience
Policies& instancePolicyMap()
{
return Policies::instancePolicyMap();
}
template<class Container>
void policy(const Container * const c)
{
std::cout << "Performing Compile Time Default Policy"
<< std::endl;
std::string obj;
if (c)
obj = c->instanceName;
else
obj = "unnamed";
std::cout << " on Object: " << obj
<< std::endl << std::endl;
}
//
//---- begin file container.h ----
//
#include "library.h"
#include <string>
#include <iostream>
template <class ElementType>
class MyContainer {
public:
MyContainer(const std::string iName) : instanceName(iName)
{}
// class implementation
// ...
// forwards the policy request
void doPolicy();
// a service that uses the policy
void performService() { doPolicy(); }
const std::string instanceName;
};
// elements for example's sake
template<class T>
struct Element1 {
// ...
};
template<class T>
struct Element2 {
// ...
};
template <class ElementType>
void MyContainer<ElementType>::doPolicy()
{
policy(this);
}
//
//---- begin file user.cpp ----
//
#include "container.h"
// policy functions used for runtime instance control
void runTimePolicy1()
{
std::cout << " runTimePolicy1() executed" << std::endl;
}
void runTimePolicy2()
{
std::cout << " runTimePolicy2() executed" << std::endl;
}
void runTimePolicy3()
{
std::cout << " runTimePolicy3() executed" << std::endl;
}
// A more specialized function overload for a compile time policy
template<class T>
void policy(const MyContainer<T> * c)
{
std::cout
<< "Performing My Compile Time Policy for "
<< "types of:" << std::endl << "MyContainer<Element1<T>"
<< std::endl;
std::string obj;
if (c)
obj = c->instanceName;
else
obj = "unnamed";
std::cout << " on Object: " << obj
<< std::endl << std::endl;
}
// A more specialized function overload for instance control
template<class T>
void policy(const MyContainer<Element2<T> > * const c)
{
std::cout << "Performing Runtime Policy: "
<< std::endl;
if (!instancePolicyMap().isRegistered(c)) {
// a per instance strategy would go here
static unsigned int r = 0;
switch(++r % 3) {
case 1:
instancePolicyMap().
registerInstance(c, &runTimePolicy1);
break;
case 2:
instancePolicyMap().
registerInstance(c, &runTimePolicy2);
break;
case 0:
default:
instancePolicyMap().
registerInstance(c, &runTimePolicy3);
}
}
std::string obj;
if (c)
obj = c->instanceName;
else
obj = "unnamed";
std::cout << " Object: " << obj << std::endl;
instancePolicyMap().policy(c);
}
int main() {
MyContainer<Element1<int> >
c("MyContainer<Element1<int> >");
MyContainer<Element2<float> >
d1("MyContainer<Element2<float> > Instance#1");
MyContainer<Element2<float> >
d2("MyContainer<Element2<float> > Instance#2");
MyContainer<Element2<float> >
d3("MyContainer<Element2<float> > Instance#3");
c.doPolicy();
d1.doPolicy();
d2.doPolicy();
d3.doPolicy();
return 0;
}
End of Listing