昌旭的博客


机器学习、编程和数学


Modern C++ Design Example(1) -- Policy

Example of Modern C++ Design Chapter 1 – Policy

Define Some Policy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
template <class T>
class OpNewCreator
{
static T* Create()
{
return new T;
}
protected:
~OpNewCreator() {}
};
template <class T>
struct MallocCreator
{
static T* Create()
{
void* buf = std::malloc(sizeof(T));
if (!buf) return 0;
return new(buf) T;
}
protected:
~MallocCreator() {}
};
template <class T>
struct PrototypeCreator
{
PrototypeCreator(T* pObj = 0)
:pPrototype_(pObj)
{}
T* Create()
{
return pPrototype_ ? pPrototype_->Clone() : 0;
}
T* GetPrototype() { return pPrototype_; }
void SetPrototype(T* pPrototype_ = pObj; )
private:
T* pPrototype_;
protected:
~PrototypeCreator() {}
};

Create Host Class

1
2
3
4
5
6
// Library Code
template <template <class> class CreationPolicy>
class WidgetManager : public CreationPolicy<Widget>
{
...
};

And now we can use our host class like this:

1
2
3
4
// Application Code
typedef WidgetManager<OpNewCreator> MyWidgetMgr;
// Or
using MyWidgetMgr = WidgetManager<OpNewCreator>;

Add Extra Function To Host Class

1
2
3
4
5
6
7
8
9
10
11
12
// Library Code
template <template <class> class CreationPolicy>
class WdigetManager : public CreationPolicy<Widget>
{
...
void SwitchPrototype(Widget* pNewPrototype)
{
CreationPolicy<Widget>& myPolicy = *this;
delete myPolicy.GetPrototype();
myPolicy.SetPrototype(pNewPrototype);
}
};

The resulting context is:

  • If the user instantiates WidgetManager with a Creator policy class that
    supports prototypes, she can use SwitchPrototype.

  • If the user instantiates WidgetManager with a Creator policy class that
    does not support prototypes and tries to use SwitchPrototype,
    a compile-time error occurs.

  • If the user instantiates WidgetManager with a Creator policy class that
    does not support prototypes and does not try to use SwitchPrototype,
    the program is valid.