@@ -13,6 +13,9 @@ defining type traits. In the :mod:`cpp-netlib` however the type traits
1313are defined on opaque tag types which serve to associate results to a
1414family of metafunctions.
1515
16+ Template Specialization
17+ -----------------------
18+
1619To illustrate this point, let's define a tag ``default_`` which we use
1720to denote the default implementation of a certain type ``foo``. For
1821instance we decide that the default string type we will use for
@@ -38,7 +41,78 @@ translate to:
3841 typedef std::string type;
3942 };
4043
41- Then in the definition of the type ``foo`` we use this type function
44+ Template Metaprogramming
45+ ------------------------
46+
47+ Starting with version 0.7, the tag dispatch mechanism changed slightly to use
48+ Boost.MPL_. The idea is still the same, although we can get a little smarter
49+ than just using template specializations. Instead of just defining an opaque
50+ type ``default_``, we use the Boost.MPL equivalent of a vector to define which
51+ root types of properties this ``default_`` tag supports. The idea is to make the
52+ opaque type ``default_`` inherit property tags which the library supports
53+ internally as definite extension points.
54+
55+ .. _Boost.MPL: http://www.boost.org/libs/mpl/index.html
56+
57+ Our definition of the ``default_`` tag will then look something like the
58+ following:
59+
60+ .. code-block:: c++
61+
62+ typedef mpl::vector<default_string> default_tags;
63+
64+ template <class Tag>
65+ struct components;
66+
67+ typedef mpl::inherit_linearly<
68+ default_tags,
69+ mpl::inherit<mpl::placeholders::_1, mpl::placeholders::_2>
70+ >::type default_;
71+
72+ template <class Tag>
73+ struct components<default_> {
74+ typedef default_tags type;
75+ };
76+
77+ In the above listing, ``default_string`` is what we call a "root" tag which is
78+ meant to be combined with other "root" tags to form composite tags. In this case
79+ our composite tag is the tag ``default_``. There are a number of these "root"
80+ tags that :mod:`cpp-netlib` provides. These are in the namespace
81+ ``boost::network::tags`` and are defined in ``boost/network/tags.hpp``.
82+
83+ Using this technique we change slightly our definition of the ``string``
84+ metafunction class into this:
85+
86+ .. code-block:: c++
87+
88+ template <class Tag>
89+ struct unsupported_tag;
90+
91+ template <class Tag>
92+ struct string :
93+ mpl::if_<
94+ is_base_of<
95+ Tag,
96+ tags::default_string
97+ >,
98+ std::string,
99+ unsupported_tag<Tag>
100+ >
101+ {};
102+
103+ Notice that we don't have the typedef for ``type`` in the body of ``string``
104+ anymore, but we do inherit from ``mpl::if_``. Since ``mpl::if_`` is a template
105+ metafunction itself, it contains a definition of the resulting ``type`` which
106+ ``string`` inherits.
107+
108+ You can see the real definition of the ``string`` metafunction in
109+ ``boost/network/traits/string.hpp``.
110+
111+ Using Tags
112+ ----------
113+
114+ Once we have the defined tag, we can then use this in the definition of our
115+ types. In the definition of the type ``foo`` we use this type function
42116``string`` and pass the tag type parameter to determine what to use as
43117the string type in the context of the type ``foo``. In code this would
44118translate into:
@@ -55,10 +129,9 @@ translate into:
55129Using this approach we can support different types of strings for
56130different tags on the type ``foo``. In case we want to use a different
57131type of string for the tag ``default_`` we only change the
58- specialization of ``string<default_>``. In the other case that we want
59- to use a different tag to define the functionality of ``foo``, all we
60- have to do is implement specializations of the type functions like
61- ``string`` for that different tag.
132+ composition of the ``string_tags`` MPL vector. For example, in :mod:`cpp-netlib`
133+ there is a root tag ``default_wstring`` which causes the ``string`` metafunction
134+ to define ``std::wstring`` as the resulting type.
62135
63136The approach also allows for the control of the structure and features
64137of types like ``foo`` based on the specialization of the tag. Whole
@@ -97,16 +170,3 @@ definition of extension points that ensures type-safety and
97170invariants. This keeps the whole extension mechanism static and yet
98171flexible.
99172
100- One drawback with this approach is the verbosity at which extensions
101- and specializations are to be done which introduces additional
102- pressure on the compiler at compile-time computations. Because this
103- technique relies heavily on the C++ template mechanism, compile times
104- may be greatly increased.
105-
106- The potential for tag and implementation explosion is also high. If
107- the implementor is not careful in controlling the number of tags and
108- type functions that take the tag as an input, it can get out of hand
109- quickly. The suggestion is to define acceptable defaults and leverage
110- re-use of existing tags as much as possible. Using Boost.MPL data
111- structures like map's and/or control structures like ``if_`` and
112- ``switch_`` can also help with heavily-used type functions.