diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 deleted file mode 100755 index 778d4ba..0000000 --- a/doc/Jamfile.v2 +++ /dev/null @@ -1,21 +0,0 @@ -import docutils ; - -import path ; -sources = [ path.glob . : *.rst ] ; -bases = $(sources:S=) ; - -# This is a path relative to the html/ subdirectory where the -# generated output will eventually be moved. -stylesheet = "--stylesheet=rst.css" ; - -for local b in $(bases) -{ - html $(b) : $(b).rst : - - # - "-gdt --traceback --trim-footnote-reference-space --footnote-references=superscript "$(stylesheet) - ; -} - -alias htmls : $(bases) ; -stage html : $(bases) ; diff --git a/doc/html/index.html b/doc/html/index.html deleted file mode 100755 index f061c4c..0000000 --- a/doc/html/index.html +++ /dev/null @@ -1,1198 +0,0 @@ - - - - - - -The Boost Parameter Library - - - -
-

The Boost Parameter Library

-

Boost

-
- --- - - - -
Abstract:

Use this library to write functions that accept -arguments by name:

-
-new_window("alert", width=10, titlebar=false);
-
-

Since named arguments can be passed in any order, they are -especially useful when a function has more than one parameter -with a useful default value.

-
-
- --- - - - - - - - - - - - -
Authors:David Abrahams, Daniel Wallin
Contact:dave@boost-consulting.com, dalwan01@student.umu.se
Organization:Boost Consulting
Date:$Date: 2005/07/18 20:34:31 $
Copyright:Copyright David Abrahams, Daniel Wallin -2005. Distributed under the Boost Software License, -Version 1.0. (See accompanying file LICENSE_1_0.txt -or copy at http://www.boost.org/LICENSE_1_0.txt)
-
- -
-
-

1   Introduction

-

In C++, arguments are normally given meaning by their positions -with respect to a parameter list. That protocol is fine when there -is at most one parameter with a default value, but when there are -even a few useful defaults, the positional interface becomes -burdensome:

-
    -
  • Since an argument's meaning is given by its position, we have to -choose an (often arbitrary) order for parameters with default -values, making some combinations of defaults unusable:

    -
    -window* new_window(
    -   char const* name, 
    -   int border_width = default_border_width,
    -   bool movable = true,
    -   bool initially_visible = true
    -   );
    -
    -const bool movability = false;
    -window* w = new_window("alert box", movability);
    -
    -

    In the example above we wanted to make an unmoveable window -with a default border_width, but instead we got a moveable -window with a border_width of zero. To get the desired -effect, we'd need to write:

    -
    -window* w = new_window(
    -   "alert box", default_border_width, movability);
    -
    -
  • -
  • It can become difficult for readers to understand the meaning of -arguments at the call site:

    -
    -window* w = new_window("alert", 1, true, false);
    -
    -

    Is this window moveable and initially invisible, or unmoveable -and initially visible? The reader needs to remember the order -of arguments to be sure.

    -
  • -
  • The author of the call may not remember the order of the -arguments either, leading to hard-to-find bugs.

    -
  • -
-

This library addresses the problems outlined above by associating -each parameter with a keyword object. Now users can identify -arguments by keyword, rather than by position:

-
-window* w = new_window("alert box", movable=false); // OK!
-
- -
-
-

2   Tutorial

-

In this section we'll show how the Parameter library can be used to -build an expressive interface to the Boost Graph library's -depth_first_search algorithm.1 After laying some groundwork -and describing the algorithm's abstract interface, we'll show you -how to build a basic implementation with keyword support. Then -we'll add support for default arguments and we'll gradually refine the -implementation with syntax improvements. Finally we'll show how to -streamline the implementation of named parameter interfaces, -improve their participation in overload resolution, and optimize -their runtime efficiency.

-
-

2.1   Headers And Namespaces

-

Most components of the Parameter library are declared in a -header named for the component. For example,

-
-#include <boost/parameter/keyword.hpp>
-
-

will ensure boost::parameter::keyword is known to the -compiler. There is also a combined header, -boost/parameter.hpp, that includes most of the library's -components. For the the rest of this tutorial, unless we say -otherwise, you can use the rule above to figure out which header -to #include to access any given component of the library.

-

Also, the examples below will also be written as if the -namespace alias

-
-namespace parameter = boost::parameter;
-
-

has been declared: we'll write parameter::xxx instead of -boost::parameter::xxx.

-
-
-

2.2   The Abstract Interface to depth_first_search

-

The Graph library's depth_first_search algorithm is a generic function accepting -from one to four arguments by reference. If all arguments were -required, its signature might be as follows:

-
-template <
-    class Graph, class DFSVisitor, class Index, class ColorMap
->
-void depth_first_search(
-  , Graph const& graph 
-  , DFSVisitor visitor
-  , typename graph_traits<g>::vertex_descriptor root_vertex
-  , IndexMap index_map
-  , ColorMap& color);
-
-

However, most of the parameters have a useful default value, as -shown in the table below.

- - ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
depth_first_search Parameters
Parameter NameDataflowDefault Value (if any)
graphinnone - this argument is required.
visitorinboost::dfs_visitor<>()
root_vertexin*vertices(graph).first
index_mapinget(boost::vertex_index,graph)
color_mapoutan iterator_property_map -created from a std::vector of -default_color_type of size -num_vertices(graph) and using -index_map for the index map.
-

Don't be intimidated by the complex default values. For the -purposes of this exercise, you don't need to understand what they -mean. Also, we'll show you how the default for color_map is -computed later in the tutorial; trust us when we say that the -complexity of its default will become valuable.

-
-
-

2.3   Defining the Keywords

-

The point of this exercise is to make it possible to call -depth_first_search with keyword arguments, leaving out any -arguments for which the default is appropriate:

-
-graphs::depth_first_search(g, color_map = my_color_map);
-
-

To make that syntax legal, there needs to be an object called -color_map with an assignment operator that can accept a -my_color_map argument. In this step we'll create one such -keyword object for each parameter. Each keyword object will be -identified by a unique keyword tag type.

-

We're going to define our interface in namespace graphs. Since -users need access to the keyword objects, but not the tag types, -we'll define the keyword objects so they're acceessible through -graphs, and we'll hide the tag types away in a tested -namespace, graphs::tag. The library provides a convenient -macro for that purpose (MSVC6.x users see this note):

-
-#include <boost/parameter/keyword.hpp>
-
-namespace graphs
-{
-  BOOST_PARAMETER_KEYWORD(tag, graph)    // Note: no semicolon
-  BOOST_PARAMETER_KEYWORD(tag, visitor)
-  BOOST_PARAMETER_KEYWORD(tag, root_vertex)
-  BOOST_PARAMETER_KEYWORD(tag, index_map)
-  BOOST_PARAMETER_KEYWORD(tag, color_map)
-}
-
-

The declaration of the visitor keyword you see here is -equivalent to:

-
-namespace graphs 
-{
-  namespace tag { struct visitor; }
-  namespace { 
-    boost::parameter::keyword<tag::visitor>& visitor
-    = boost::parameter::keyword<tag::visitor>::get();
-  }
-}
-
-

This “fancy dance” involving the unnamed namespace and references -is all done to avoid violating the One Definition Rule (ODR)2 when the named parameter interface is used by function -templates that are instantiated in multiple translation -units.

-
-
-

2.4   Defining the Implementation Function

-

Next we can write the skeleton of the function that implements -the core of depth_first_search:

-
-namespace graphs { namespace core
-{
-  template <class ArgumentPack>
-  void depth_first_search(ArgumentPack const& args)
-  {
-      // algorithm implementation goes here
-  }
-}}
-
-

core::depth_first_search has an ArgumentPack -parameter: a bundle of references to the arguments that the caller -passes to the algorithm, tagged with their keywords. To extract -each parameter, just pass its keyword object to the -ArgumentPack's subscript operator. Just to get a feel for how -things work, let's add some temporary code to print the arguments:

-
-namespace graphs { namespace core
-{
-  template <class ArgumentPack>
-  void depth_first_search(ArgumentPack const& args)
-  {
-      std::cout << "graph:\t" << args[graph] << std::endl;
-      std::cout << "visitor:\t" << args[visitor] << std::endl;
-      std::cout << "root_vertex:\t" << args[root_vertex] << std::endl;
-      std::cout << "index_map:\t" << args[index_map] << std::endl;
-      std::cout << "color_map:\t" << args[color_map] << std::endl;
-  }
-}} // graphs::core
-
-

It's unlikely that many of the arguments the caller will eventually -pass to depth_first_search can be printed, but for now the code -above will give us something to experiment with. To see the -keywords in action, we can write a little test driver:

-
-int main()
-{
-    using namespace graphs;
-
-    core::depth_first_search((
-      graph = 'G', visitor = 2, root_vertex = 3.5, 
-      index_map = "hello, world", color_map = false));
-}
-
-

An overloaded comma operator (operator,) combines the results -of assigning to each keyword object into a single ArgumentPack -object that gets passed on to core::depth_first_search. The -extra set of parentheses you see in the example above are required: -without them, each assignment would be interpreted as a separate -function argument and the comma operator wouldn't take effect. -We'll show you how to get rid of the extra parentheses later in -this tutorial.

-

Of course, we can pass the arguments in any order:

-
-int main()
-{
-    using namespace graphs;
-
-    core::depth_first_search((
-      root_vertex = 3.5, graph = 'G', color_map = false, 
-      index_map = "hello, world", visitor = 2));
-}
-
-

either of the two programs above will print:

-
-graph:       G
-visitor:     2
-root_vertex: 3.5
-index_map:   hello, world
-color_map:   false
-
-
-
-

2.5   Adding Defaults

-

Currently, all the arguments to depth_first_search are -required. If any parameter can't be found, there will be a -compilation error where we try to extract it from the -ArgumentPack using the subscript operator. To make it -legal to omit an argument we need to give it a default value.

-
-

2.5.1   Syntax

-

We can make any of the parameters optional by following its keyword -with the | operator and the parameter's default value within -the square brackets. In the following example, we've given -root_vertex a default of 42 and color_map a default of -"hello, world".

-
-namespace graphs { namespace core
-{
-  template <class ArgumentPack>
-  void depth_first_search(ArgumentPack const& args)
-  {
-      std::cout << "graph:\t" << args[graph] << std::endl;
-      std::cout << "visitor:\t" << args[visitor] << std::endl;
-      std::cout << "root_vertex:\t" << args[root_vertex|42] << std::endl;
-      std::cout << "index_map:\t" << args[index_map] << std::endl;
-      std::cout << "color_map:\t" << args[color_map|"hello, world"] << std::endl;
-  }
-}} // graphs::core
-
-

Now we can invoke the function without supplying color_map or -root_vertex:

-
-core::depth_first_search((
-  graph = 'G', index_map = "index", visitor = 6));
-
-

The call above would print:

-
-graph:       G
-visitor:     6
-root_vertex: 42
-index_map:   index
-color_map:   hello, world
-
-
-

Important

-

The index expression args[…] always yields a reference -that is bound either to the actual argument passed by the caller -or, if no argument is passed explicitly, to the specified -default value.

-
-
-
-

2.5.2   Getting More Realistic

-

Now it's time to put some more realistic defaults in place. We'll -have to give up our print statements—at least if we want to see the -defaults work—since, the default values of these -parameters generally aren't printable.

-

Instead, we'll connect local variables to the arguments and use -those in our algorithm:

-
-namespace graphs { namespace core
-{
-  template <class ArgumentPack>
-  void depth_first_search(ArgumentPack const& args)
-  {
-      Graph   g = args[graph];
-      Visitor v = args[visitor|default-expression1];
-      Vertex  s = args[root_vertex|default-expression2];
-      Index   i = args[index_map|default-expression3];
-      Color   c = args[visitor|default-expression4];
-
-      …use g, v, s, i, and c to implement the algorithm…
-  }
-}} // graphs::core
-
-

We'll insert the default expressions in a moment, but first we -need to come up with the types Graph, Visitor, Vertex, -Index, and Color.

-
-
-

2.5.3   The binding Metafunction

-

To compute the type of a parameter we can use a Metafunction -called binding:

-
-binding<ArgumentPack, Keyword, Default = void>
-{ typedef see text type; };
-
-

where Default is the type of the default argument, if any.

-

For example, to declare and initialize g above, we could write:

-
-typedef typename parameter::binding<
-  ArgumentPack,tag::graph
->::type Graph;
-
-Graph g = args[graph];
-
-

As shown in the parameter table, graph has no default, so -the binding invocation for Graph takes only two arguments. -The default visitor is boost::dfs_visitor<>(), so the -binding invocation for Visitor takes three arguments:

-
-typedef typename parameter::binding<
-  ArgumentPack,tag::visitor,boost::dfs_visitor<>
->::type Visitor;
-
-Visitor v = args[visitor|boost::dfs_visitor<>()];
-
-

Note that the default visitor is supplied as a temporary -instance of dfs_visitor. Because args[…] always yields -a reference, making v a reference would cause it to bind to -that temporary, and immediately dangle. Therefore, it's crucial -that we passed dfs_visitor<>, and not dfs_visitor<> -const&, as the last argument to binding.

-
-

Important

-

Never pass binding a reference type as the default unless -you know that the default value passed to the ArgumentPack's -indexing operator will outlive the reference you'll bind to it.

-
-

Sometimes there's no need to use binding at all. The -root_vertex argument is required to be of the graph's -vertex_descriptor type,3 so we can just -use that knowledge to bypass binding altogether.

-
-typename boost::graph_traits<Graph>::vertex_descriptor
-  s = args[root_vertex|*vertices(g).first];
-
-
-
-

2.5.4   Beyond Ordinary Default Arguments

-

Here's how you might write the declaration for the index_map -parameter:

-
-typedef typename parameter::binding<
-    ArgumentPack
-  , tag::index_map
-  , typename boost::property_map<Graph, vertex_index_t>::const_type
->::type Index;
-
-Index i = args[index_map|get(boost::vertex_index,g)];
-
-

Notice two capabilities we've gained over what -plain C++ default arguments provide:

-
    -
  1. The default value of the index parameter depends on the -value of the graph parameter. That's illegal in plain C++:

    -
    -void f(int graph, int index = graph + 1); // error
    -
    -
  2. -
  3. The index parameter has a useful default, yet it is -templated and its type can be deduced when an index -argument is explicitly specified by the caller. In plain C++, you -can specify a default value for a parameter with deduced type, -but it's not very useful:

    -
    -template <class Index>
    -int f(Index index = 42);  // OK
    -int y = f();                // error; can't deduce Index
    -
    -
  4. -
-
-
-
-

2.6   Syntactic Refinement

-

In this section we'll describe how you can allow callers to invoke -depth_first_search with just one pair of parentheses, and to -omit keywords where appropriate.

-
-

2.6.1   Describing the Positional Argument Order

-

First, we'll need to build a type that describes the allowed -parameters and their ordering when passed positionally. This type -is known as a ParameterSpec (MSVC6.x users see this note):

-
-namespace graphs
-{
-  typedef parameter::parameters<
-      tag::graph
-    , tag::visitor
-    , tag::root_vertex
-    , tag::index_map
-    , tag::color_map
-  > dfs_params;
-}
-
-

The parameters template supplies a function-call -operator that groups all its arguments into an ArgumentPack. Any -arguments passed to it without a keyword label will be associated -with a parameter according to its position in the ParameterSpec. -So for example, given an object p of type dfs_params,

-
-p('G', index_map=1)
-
-

yields an ArgumentPack whose graph parameter has a value of -'G', and whose index_map parameter has a value of 1.

-
-
-

2.6.2   Forwarding Functions

-

Next we need a family of overloaded depth_first_search function -templates that can be called with anywhere from one to five -arguments. These forwarding functions will invoke an instance of -dfs_params as a function object, passing their parameters -to its operator() and forwarding the result on to -core::depth_first_search:

-
-namespace graphs
-{
-  template <class A0>
-  void depth_first_search(A0 const& a0)
-  {
-     core::depth_first_search(dfs_params()(a0));
-  }
-
-  template <class A0, class A1>
-  void depth_first_search(A0 const& a0, A1 const& a1)
-  {
-     core::depth_first_search(dfs_params()(a0,a1));
-  } 
-  .
-  .
-  .
- 
-  template <class A0, class A1, …class A4>
-  void depth_first_search(A0 const& a0, A1 const& a1, …A4 const& a4)
-  {
-     core::depth_first_search(dfs_params()(a0,a1,a2,a3,a4));
-  }
-}
-
-

That's it! We can now call graphs::depth_first_search with -from one to five arguments passed positionally or via keyword.

-
-
-

2.6.3   “Out” Parameters

-

Well, that's not quite it. When passing arguments by keyword, -the keyword object's assignment operator yields a temporary -ArgumentPack object. A conforming C++ compiler will refuse to -bind a non-const reference to a temporary, so to support a -keyword interface for all arguments, the overload set above must -take its arguments by const reference. On the other hand—as -you may recall from the parameter tablecolor_map is an -“out” parameter, so it really should be passed by non-const -reference.

-

A keyword object has a pair of operator= overloads that ensure -we can pass anything—temporary or not, const or not—by name, -while preserving the mutability of non-temporaries:

-
-template <class A>                  // handles non-const, 
-ArgumentPack operator=(A&);       // non-temporary objects
-
-template <class A>                  // handles const objects
-ArgumentPack operator=(A const&); // and temporaries
-
-

However, when an “out” parameter is passed positionally, there's no -keyword object involved. With our depth_first_search overload -set above, the color_map will be passed by const reference, -and compilation will fail when mutating operations are used on it. -The simple solution is to add another overload that takes a -non-const reference in the position of the “out” parameter:

-
-template <class A0, class A1, …class A4>
-void depth_first_search(A0 const& a0, A1 const& a1, …A4& a4)
-{
-    core::depth_first_search(dfs_params()(a0,a1,a2,a3,a4));
-}
-
-

That approach works nicely because there is only one “out” -parameter and it is in the last position. If color_map had -been the first parameter, we would have needed ten overloads. In -the worst case—where the function has five “out” parameters—25 or 32 overloads would be required. This “forwarding -problem” is well-known to generic library authors, and the C++ -standard committee is working on a proposal to address it. In -the meantime, you might consider using Boost.Preprocessor to -generate the overloads you need.

-

If it is impractical for you to generate or write the overloads -that would be required for positional “out” arguments to be passed -directly, you still have the option to ask users to pass them -through boost::ref, which will ensure that the algorithm implementation -sees a non-const reference:

-
-depth_first_search(g, v, s, i, boost::ref(c));
-
-
-
-

2.6.4   Generating Forwarding Functions with Macros

-

To remove some of the tedium of writing overloaded forwarding -functions, the library supplies a macro, suitably located in -boost/parameter/macros.hpp, that will generate free function -overloads for you:

-
-BOOST_PARAMETER_FUN(void, depth_first_search, 1, 5, dfs_params);
-
-

will generate a family of five depth_first_search overloads, in -the current scope, that pass their arguments through -dfs_params. Instead of core::depth_first_search, these -overloads will forward the ArgumentPack on to a function called -depth_first_search_with_named_params, also in the current -scope. It's up to you to implement that function. You could -simply transplant the body of core::depth_first_search into -depth_first_search_with_named_params if you were going to use -this approach.

-

Note that BOOST_PARAMETER_FUN only takes arguments by const -reference, so you will have to add any additional overloads -required to handle positional “out” parameters yourself. We are -looking into providing a more sophisticated set of macros to -address this problem and others, for an upcoming release of Boost.

-
-
-
-

2.7   Controlling Overload Resolution

-

The parameters of our templated forwarding functions are completely -general; in fact, they're a perfect match for any argument type -whatsoever. The problems with exposing such general function -templates have been the subject of much discussion, especially in -the presence of unqualified calls. Probably the safest thing -to do is to isolate the forwarding functions in a namespace -containing no types5, but often we'd like our functions -to play nicely with argument-dependent lookup and other function -overloads. In that case, it's neccessary to remove the functions -from the overload set when the passed argument types aren't -appropriate.

-
-

2.7.1   Updating the ParameterSpec

-

This sort of overload control can be accomplished in C++ by taking -advantage of the SFINAE (Substitution Failure Is Not An Error) -rule.6 You can take advantage of the Parameter library's -built-in SFINAE support by using the following class templates in -your ParameterSpec:

-
-template< class KeywordTag, class Predicate = unspecified >
-struct required;
-
-template< class KeywordTag, class Predicate = unspecified >
-struct optional;
-
-

Instead of using keyword tags directly, we can wrap them in -required and optional to indicate which function parameters -are required, and optionally pass Predicates to describe the -type requirements for each function parameter. The Predicate -argument must be a unary MPL lambda expression that, when -applied to the actual type of the argument, indicates whether that -argument type meets the function's requirements for that parameter -position.

-

For example, let's say we want to restrict depth_first_search() so that -the graph parameter is required and the root_vertex -parameter is convertible to int. We might write:

-
-#include <boost/type_traits/is_convertible.hpp>
-#include <boost/mpl/placeholders.hpp>
-namespace graphs
-{
-  using namespace boost::mpl::placeholders;
-
-  struct dfs_params
-    : parameter::parameters<
-          parameter::required<tag::graph>
-        , parameter::optional<tag::visitor>
-        , parameter::optional<
-              tag::root_vertex, boost::is_convertible<_,int>
-          >
-        , parameter::optional<tag::index_map>
-        , parameter::optional<tag::color_map>
-      >
-  {};
-}
-
-
-
-

2.7.2   Applying SFINAE to the Overload Set

-

Now we add a special defaulted argument to each of our -depth_first_search overloads:

-
-namespace graphs
-{
-  template <class A0>
-  void depth_first_search(
-      A0 const& a0
-    , typename dfs_params::match<A0>::type p = dfs_params())
-  {
-     core::depth_first_search(p(a0));
-  }
-
-  template <class A0, class A1>
-  void depth_first_search(
-      A0 const& a0, A1 const& a1
-    , typename dfs_params::match<A0,A1>::type p = dfs_params())
-  {
-     core::depth_first_search(p(a0,a1));
-  } 
-  .
-  .
-  .
- 
-  template <class A0, class A1, …class A4>
-  void depth_first_search(
-      A0 const& a0, A1 const& a1, …A4 const& A4
-    , typename dfs_params::match<A0,A1,A2,A3,A4>::type p = dfs_params())
-  {
-     core::depth_first_search(p(a0,a1,a2,a3,a4));
-  }
-}
-
-

These additional parameters are not intended to be used directly -by callers; they merely trigger SFINAE by becoming illegal types -when the name argument is not convertible to const -char*. The BOOST_PARAMETER_FUN macro described earlier -adds these extra function parameters for you (Borland users see -this note).

-
-
-

2.7.3   Reducing Boilerplate With Macros

-

The library provides a macro you can use to eliminate some of the -repetetiveness of the declaring the optional parameters. -BOOST_PARAMETER_MATCH takes three arguments: the -ParameterSpec, a Boost.Preprocessor sequence of the function -argument types, and a name for the defaulted function parameter -(p, above), and it generates the appropriate defaulted -argument. So we could shorten the overload set definition as -follows:

-
-namespace graphs
-{
-  template <class A0>
-  void depth_first_search(
-      A0 const& a0
-    , BOOST_PARAMETER_MATCH(dfs_params, (A0), p))
-  {
-     core::depth_first_search(p(a0));
-  }
-
-  template <class A0, class A1>
-  void depth_first_search(
-      A0 const& a0, A1 const& a1
-    , BOOST_PARAMETER_MATCH(dfs_params, (A0)(A1), p))
-  {
-     core::depth_first_search(p(a0,a1));
-  } 
-  .
-  .
-  .
- 
-  template <class A0, class A1, …class A4>
-  void depth_first_search(
-      A0 const& a0, A1 const& a1, …A4 const& A4
-    , BOOST_PARAMETER_MATCH(dfs_params, (A0)(A1)…(A4), p))
-  {
-     core::depth_first_search(p(a0,a1,a2,a3,a4));
-  }
-}
-
-
-
-
-

2.8   Efficiency Issues

-

The color_map parameter gives us a few efficiency issues to -consider. Here's a first cut at extraction and binding:

-
-typedef 
-  vector_property_map<boost::default_color_type, Index>
-default_color_map;
-
-typename parameter::binding<
-    ArgumentPack
-  , tag::color_map
-  , default_color_map
->::type color = args[color_map|default_color_map(num_vertices(g),i)];
-
-
-

2.8.1   Eliminating Copies

-

The library has no way to know whether an explicitly-supplied -argument is expensive to copy (or even if it is copyable at all), -so binding<…,k,…>::type is always a reference type when the -k parameter is supplied by the caller. Since args[…] -yields a reference to the actual argument, color will be bound -to the actual color_map argument and no copying will be done.

-

As described above, because the default is a temporary, it's -important that color be a non-reference when the default is -used. In that case, the default value will be copied into -color. If we store the default in a named variable, though, -color can be a reference, thereby eliminating the copy:

-
-default_color_map default_color(num_vertices(g),i);
-
-typename parameter::binding<
-    ArgumentPack
-  , tag::color_map
-  , default_color_map&
->::type color = args[color_map|default_color];
-
-
-

Hint

-

To avoid making needless copies, pass a reference to the -default type as the third argument to binding.

-
-
-
-

2.8.2   Lazy Default Computation

-

Of course it's nice to avoid copying default_color, but the -more important cost is that of constructing it in the first -place. A vector_property_map is cheap to copy, since it holds -its elements via a shared_ptr. On the other hand, construction of -default_color costs at least two dynamic memory allocations and -num_vertices(g) copies; it would be better to avoid doing this -work when the default value won't be needed.

-

To that end, the library allows us to supply a callable object -that—if no argument was supplied by the caller—will be invoked to -construct the default value. Instead of following the keyword with -the | operator, we'll use || and follow it with a -nullary (zero-argument) function object that constructs a -default_color_map. Here, we build the function object using -Boost.Lambda:4

-
-// After #include <boost/lambda/construct.hpp>
-typename parameter::binding<
-    ArgumentPack
-  , tag::color_map
-  , default_color_map
->::type color = args[
-  color_map
-  || boost::lambda::construct<default_color_map>(num_vertices(g),i)
-];
-
- -
-
-

2.8.3   Default Forwarding

-

Types that are expensive to construct yet cheap to copy aren't all -that typical, and even copying the color map is more expensive than -we might like. It might be nice to avoid both needless -construction and needless copying of the default color map. The -simplest way to achieve that is to avoid naming it altogether, at -least not in core::depth_first_search. Instead, we'll -introduce another function template to implement the actual -algorithm:

-
-namespace graphs { namespace core
-{
-  template <class G, class V, class S, class I, class C>
-  void dfs_impl(G& g, V& v, S& s, I& i, C& c)
-  {
-      …actual algorithm implementation…
-  }
-}}
-
-

Then, in core::depth_first_search, we'll simply forward the -result of indexing args to core::dfs_impl:

-
-core::dfs_impl( 
-    g,v,s,i
-  , args[
-      color_map
-      || boost::lambda::construct<default_color_map>(num_vertices(g),i)
-    ]);
-
-

In real code, after going to the trouble to write dfs_impl, -we'd probably just forward all the arguments.

-
-
-

2.8.4   Dispatching Based on the Presence of a Default

-

In fact, the Graph library itself constructs a slightly different -color_map, to avoid even the overhead of initializing a -shared_ptr:

-
-std::vector<boost::default_color_type> 
-  color_vec(num_vertices(g));
-
-boost::iterator_property_map<
-    typename std::vector<
-       boost::default_color_type
-    >::iterator
-  , Index
-> c(color_vec.begin(), i);
-
-

To avoid instantiating that code when it isn't needed, we'll have -to find a way to select different function implementations, at -compile time, based on whether a color_map argument was -supplied. By using tag dispatching on the presence of a -color_map argument, we can do just that:

-
-#include <boost/type_traits/is_same.hpp>
-#include <boost/mpl/bool.hpp>
-
-namespace graphs { namespace core {
-
-  template <class ArgumentPack>
-  void dfs_dispatch(ArgumentPack& args, mpl::true_)
-  {
-      …use the color map computed in the previous example…
-  }
-  
-  template <class ArgumentPack>
-  void dfs_dispatch(ArgumentPack& args, mpl::false_)
-  {
-      …use args[color]…
-  }
-  
-  template <class ArgumentPack>
-  void depth_first_search(ArgumentPack& args)
-  {
-      typedef typename binding<args,tag::color>::type color_;
-      core::dfs_dispatch(args, boost::is_same<color_,void>());
-  }
-}}
-
-

We've used the fact that the default for binding's third -argument is void: because specializations of is_same are -bool-valued MPL Integral Constants derived either -from mpl::true_ or mpl::false_, the appropriate -dfs_dispatch implementation will be selected.

-
-
-
-
-

3   Portability Considerations

-

Use the regression test results for the latest Boost release of -the Parameter library to see how it fares on your favorite -compiler. Additionally, you may need to be aware of the following -issues and workarounds for particular compilers.

-
-

3.1   No SFINAE Support

-

Some older compilers don't support SFINAE. If your compiler meets -that criterion, then Boost headers will #define the preprocessor -symbol BOOST_NO_SFINAE, and uses of parameters<…>::match and -BOOST_PARAMETER_MATCH will be harmless, but will have no effect.

-
-
-

3.2   No Support for result_of

-

Lazy default computation relies on the result_of class -template to compute the types of default arguments given the type -of the function object that constructs them. On compilers that -don't support result_of, BOOST_NO_RESULT_OF will be -#defined, and the compiler will expect the function object to -contain a nested type name, result_type, that indicates its -return type when invoked without arguments. To use an ordinary -function as a default generator on those compilers, you'll need to -wrap it in a class that provides result_type as a typedef -and invokes the function via its operator().

-
-
-

3.3   Can't Declare ParameterSpec via typedef

-

In principle you can declare a ParameterSpec as a typedef -for a specialization of parameters<…>, but Microsoft Visual C++ -6.x has been seen to choke on that usage. The workaround is to use -inheritance and declare your ParameterSpec as a class:

-
-struct dfs_parameters
-  : parameter::parameters<
-      tag::graph, tag::visitor, tag::root_vertex
-    , tag::index_map, tag::color_map
-> {};
-
-
-
-

3.4   Default Arguments Unsupported on Nested Templates

-

As of this writing, Borland compilers don't support the use of -default template arguments on member class templates. As a result, -you have to supply BOOST_PARAMETER_MAX_ARITY arguments to every -use of parameters<…>::match. Since the actual defaults used -are unspecified, the workaround is to use -BOOST_PARAMETER_MATCH to declare default arguments for SFINAE.

-
-
-

3.5   Compiler Can't See References In Unnamed Namespace

-

If you use Microsoft Visual C++ 6.x, you may find that the compiler -has trouble finding your keyword objects. This problem has been -observed, but only on this one compiler, and it disappeared as the -test code evolved, so we suggest you use it only as a last resort -rather than as a preventative measure. The solution is to add -using-declarations to force the names to be available in the -enclosing namespace without qualification:

-
-namespace graphs
-{
-  using graphs::graph;
-  using graphs::visitor;
-  using graphs::root_vertex;
-  using graphs::index_map;
-  using graphs::color_map;
-}
-
-
-
-
-

4   Reference

-

Follow this link to the Boost.Parameter reference -documentation.

-
-
-

5   Acknowledgements

-

The authors would like to thank all the Boosters who participated -in the review of this library and its documentation, most -especially our review manager, Doug Gregor.

-
- - - - - -
[1]As of Boost 1.33.0 the Graph library was still -using an older named parameter mechanism, but there are -plans to change it to use Boost.Parameter (this library) in an -upcoming release, while keeping the old interface available for -backward-compatibility.
- - - - - -
[2]The One Definition Rule says that any given entity in -a C++ program must have the same definition in all translation -units (object files) that make up a program.
- - - - - -
[3]If you're not familiar with the Boost Graph -Library, don't worry about the meaning of any -Graph-library-specific details you encounter. In this case you -could replace all mentions of vertex descriptor types with -int in the text, and your understanding of the Parameter -library wouldn't suffer.
- - - - - -
[4]

The Lambda library is known not to work on some -less-conformant compilers. When using one of those you could -define

-
-  template <class T>
-  struct construct2
-  {
-      typedef T result_type;
-
-      template <class A1, class A2>
-      T operator()(A1 a1, A2 a2) { return T(a1,a2); }
-  };
-
-and use `Boost.Bind`_ to generate the function object::
-
-  boost::bind(construct2<default_color_map>(),num_vertices(g),i)
-
-
- - - - - -
[5]

You can always give the illusion that the function -lives in an outer namespace by applying a using-declaration:

-
-namespace foo_overloads
-{
-  // foo declarations here
-  void foo() { ... }
-  ...
-}
-using foo_overloads::foo;  
-
-
- - - - - -
[6]If type substitution during the instantiation of a -function template results in an invalid type, no compilation -error is emitted; instead the overload is removed from the -overload set. By producing an invalid type in the function -signature depending on the result of some condition, whether or -not an overload is considered during overload resolution can be -controlled. The technique is formalized in the enable_if -utility. See -http://www.semantics.org/once_weakly/w02_SFINAE.pdf for more -information on SFINAE.
-
-
- - - - diff --git a/doc/html/reference.html b/doc/html/reference.html deleted file mode 100755 index 99dfed5..0000000 --- a/doc/html/reference.html +++ /dev/null @@ -1,785 +0,0 @@ - - - - - - -The Boost Parameter Library Reference Documentation - - - -
-

The Boost Parameter Library Reference Documentation

-

Boost

- --- - - - - - - - - - - - -
Authors:David Abrahams, Daniel Wallin
Contact:dave@boost-consulting.com, dalwan01@student.umu.se
organization:Boost Consulting
date:$Date: 2005/07/17 19:53:01 $
copyright:Copyright David Abrahams, Daniel Wallin -2005. Distributed under the Boost Software License, -Version 1.0. (See accompanying file LICENSE_1_0.txt -or copy at http://www.boost.org/LICENSE_1_0.txt)
-
- -
-
-

1   Preliminaries

-

This section covers some basic information you'll need to know in -order to understand this reference

-
-

1.1   Namespaces

-

In this document, all unqualified identifiers should be assumed to -be defined in namespace boost::parameter unless otherwise -specified.

-
-
-

1.2   Exceptions

-

No operation described in this document -throws an exception unless otherwise specified.

-
-
-

1.3   Thread Safety

-

All components of this library can be used safely from multiple -threads without synchronization.1

-
-
-

1.4   Typography

-

Names written in sans serif type represent concepts.

-

In code blocks, italic type represents unspecified text that -satisfies the requirements given in the detailed description that -follows the code block.

-

In a specification of the tokens generated by a macro, bold -type is used to highlight the position of the expanded macro -argument in the result.

-

The special character β represents the value of BOOST_PARAMETER_MAX_ARITY.

-
-
-
-
-

2   Terminology

-
-
keyword
-
The name of a function parameter.
-
-
-
keyword tag type
-
A type used to uniquely identify a function parameter. Typically -its name will be the same as that of the parameter.
-
-
-
positional argument
-
An argument passed with no explicit keyword. Its parameter is -determined in the usual C++ way: by position with respect to a -parameter list.
-
-
-
tag type
-
Shorthand for “keyword tag type.”
-
-
-
keyword object
-
An instance of keyword <T> for some tag type T.
-
-
-
tagged reference
-

An object whose type is associated with a keyword tag type (the -object's keyword), and that holds a reference (to the object's -value).

-

As a shorthand, a “tagged reference to x” means a tagged -reference whose value is x.

-
-
-
-
tagged default
-
A tagged reference whose value represents the value of a -default argument.
-
-
-
tagged lazy default
-
A tagged reference whose value, when invoked with no -arguments, computes a default argument value.
-
-
-
intended argument type
-
The intended argument type of a single-element ArgumentPack is the -type of its element's value. The intended argument type of any other -type X is X itself.
-
-
-

Note

-

In this reference, we will use concept names (and other names) -to describe both types and objects, depending on context. So -for example, “an ArgumentPack” can refer to a type that -models ArgumentPack or an object of such a type.

-
-
-
-
-

3   Concepts

-

This section describes the generic type concepts used by the Parameter library.

-
-

3.1   ArgumentPack

-

An ArgumentPack is a collection of tagged references to the -actual arguments passed to a function.

-
-

Requirements

-

In the table below,

- -

Any exceptions are thrown from the invocation of w's value -will be propagated to the caller.

- - ------ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ArgumentPack requirements
ExpressionTypeRequirementsSemantics/Notes
x[u]binding<A,K>::typex contains an -element b whose -keyword is KReturns b's value (by -reference).
x[u]binding<A,L,D>::typenoneIf x contains an element b whose -keyword is the same as u's, -returns b's value (by -reference). Otherwise, returns u's value.
x[w]lazy_binding<A,M,E>::typenoneIf x contains an element b whose -keyword is the same as w's, -returns b's value (by -reference). Otherwise, invokes w's value and returns the result.
x, zModel of ArgumentPacknoneReturns an ArgumentPack containing -all the elements of both x and -z.
-
-
-
-

3.2   ParameterSpec

-

A ParameterSpec describes the type requirements for arguments -corresponding to a given keyword and indicates whether the argument -is optional or required. The table below details the allowed forms -and describes their condition for satisfaction by an actual -argument type. In each row,

- - - ----- - - - - - - - - - - - - - - - - - - - - -
ParameterSpec allowed forms and conditions of satisfaction
TypeA requiredCondition A must satisfy
keyword<K>non/a
optional<K,F>nompl::apply<F,A>::type::value -is true.
required<K,F>yesmpl::apply<F,A>::type::value -is true.
-

The information in a ParameterSpec is used to limit the -arguments that will be matched by forwarding functions.

-
-
-
-
-

4   Class Templates

-
-

4.1   keyword

-

The type of every keyword object is a specialization of keyword.

- --- - - - -
Defined in:boost/parameter/keyword.hpp
-
-template <class Tag>
-struct keyword
-{
-    template <class T> ArgumentPack operator=(T& value) const;
-    template <class T> ArgumentPack operator=(T const& value) const;
-
-    template <class T> tagged default operator|(T& x) const;
-    template <class T> tagged default operator|(T const& x) const;
-
-    template <class F> tagged lazy default operator||(F const&) const;
-
-    static keyword<Tag>& get();
-};
-
-
-
operator=
-
-template <class T> ArgumentPack operator=(T& value) const;
-template <class T> ArgumentPack operator=(T const& value) const;
-
- --- - - - - - -
Requires:nothing
Returns:an ArgumentPack containing a single tagged reference to -value with keyword Tag
-
-
-
-
operator|
-
-template <class T> tagged default operator|(T& x) const;
-template <class T> tagged default operator|(T const& x) const;
-
- --- - - - -
Returns:a tagged default with value x and keyword Tag.
-
-
-
-
operator||
-
-template <class F> tagged lazy default operator||(F const& g) const;
-
- --- - - - - - -
Requires:g() is valid, with type boost::result_of<F()>::type.2
Returns:a tagged lazy default with value g and keyword Tag.
-
-
-
-
get
-
-static keyword<Tag>& get();
-
- --- - - - - - -
Returns:a “singleton instance”: the same object will be -returned on each invocation of get().
Thread Safety:get() can be called from multiple threads -simultaneously.
-
-
-
-
-

4.2   parameters

-

Provides an interface for assembling the actual arguments to a -forwarding function into an ArgumentPack, in which any -positional arguments will be tagged according to the -corresponding template argument to parameters.

- --- - - - -
Defined in:boost/parameter/parameters.hpp
-
-template <class P0 = unspecified, class P1 = unspecified, …class Pβ = unspecified>
-struct parameters
-{
-    template <class A0, class A1 = unspecified, …class Aβ = unspecified>
-    struct match
-    {
-        typedef … type;
-    };
-
-    template <class A0>
-    ArgumentPack operator()(A0 const& a0) const;
-
-    template <class A0, class A1>
-    ArgumentPack operator()(A0 const& a0, A1 const& a1) const; 
-   .
-   .
-   .
- 
-    template <class A0, class A1, …class Aβ>
-    ArgumentPack operator()(A0 const& a0, A1 const& a1, …Aβ const& aβ) const;
-};
-
- --- - - - -
Requires:P0, P1, … Pβ are models of ParameterSpec.
-
-

Note

-

In this section, Ri and Ki are defined as -follows, for any argument type Ai:

-
-
- -

-
-
if Ai is a result type of keyword<T>::operator=
-
then
-
-
Ki is T
-
-
else
-
-
Ki is Pi's keyword tag type.
-
-
-
-
-
-
-
match
-

A Metafunction used to remove a forwarding function from overload resolution.

- --- - - - -
Returns:if P0, P1, …Pβ are satisfied (see -below), then parameters<P0,P1,…Pβ>. Otherwise, -match<A0,A1,…Aβ>::type is not defined.
-

P0, P1, …Pβ are satisfied if, for -every j in 0…β, either:

-
    -
  • Pj is the unspecified default
  • -
  • or, Pj is a specialization of keyword,
  • -
  • or, Pj is optional <X,F> and either
      -
    • X is not Ki for any i,
    • -
    • or X is some Ki and mpl::apply<F,Ri>::type::value is true
    • -
    -
  • -
  • or, Pj is required <X,F>, and
      -
    • X is some Ki, and
    • -
    • mpl::apply<F,Ri>::type::value is true
    • -
    -
  • -
-
-
-
-
operator()
-
-template <class A0> ArgumentPack operator()(A0 const& a0) const; 
-  .
-  .
-  .
- 
-template <class A0, …class Aβ> ArgumentPack operator()(A0 const& a0, …Aβ const& aβ) const;
-
- --- - - - -
Returns:

An ArgumentPack containing, for each ai,

-
    -
  • if ai, is a single-element ArgumentPack, its element
  • -
  • Otherwise, a tagged reference with keyword Ki and value ai
  • -
-
-
-
-
-
-

4.3   optional, required

-

These templates describe the requirements on a function parameter.

- --- - - - -
Defined in:boost/parameter/parameters.hpp
- --- - - - - -
Specializations model:
 ParameterSpec
-
-template <class Tag, class Predicate = unspecified>
-struct optional;
-
-template <class Tag, class Predicate = unspecified>
-struct required;
-
-

The default value of Predicate is an unspecified Metafunction that returns -mpl::true_ for any argument.

-
-
-
-
-

5   Metafunctions

-

A Metafunction is conceptually a function that operates on, and -returns, C++ types.

-
-

5.1   binding

-

Returns the result type of indexing an argument pack with a -keyword tag type or with a tagged default.

- --- - - - -
Defined n:boost/parameter/binding.hpp
-
-template <class A, class K, class D = void>
-struct binding
-{
-    typedef … type;
-};
-
- --- - - - - - -
Requires:A is a model of ArgumentPack.
Returns:the reference type of the tagged reference in A -having keyword tag type K, if any. If no such tagged reference exists, returns D.
-
-
-

5.2   lazy_binding

-

Returns the result type of indexing an argument pack with a tagged lazy default.

- --- - - - -
Defined in:boost/parameter/binding.hpp
-
-template <class A, class K, class F>
-struct lazy_binding
-{
-    typedef … type;
-};
-
- --- - - - - - -
Requires:A is a model of ArgumentPack.
Returns:the reference type of the tagged reference in A -having keyword tag type K, if any. If no such tagged reference exists, returns boost::result_of<F()>::type.2
-
-
-
-
-

6   Code Generation Macros

-

Macros in this section can be used to ease the writing of code -using the Parameter libray by eliminating repetitive boilerplate.

-
-

6.1   BOOST_PARAMETER_FUN(r,n,l,h,p)

-

Generates a sequence of forwarding function templates named -n, with arities ranging from l to h , returning r, -and using p to control overload resolution and assign tags to -positional arguments.

- --- - - - -
Defined in:boost/parameter/macros.hpp
- --- - - - -
Requires:l and h are nonnegative integer tokens such -that l < h
-
-
Generates
-
-template <class A1, class A2, …class A##l>
-r name(
-    A1 const& a1, A2 const& a2, …Al const& xl
-  , typename p::match<A1,A2,…Al>::type p = p())
-{
-   return name_with_named_params(p(x1,x2,…xl));
-}
-
-template <class A1, class A2, …class Al, class A##BOOST_PP_INC(l)>
-r name(
-    A1 const& a1, A2 const& a2, …Al const& xl
-  , A##BOOST_PP_INC(l) const& x##BOOST_PP_INC(l)
-  , typename p::match<A1,A2,…Al,A##BOOST_PP_INC(l)>::type p = p())
-{
-   return name_with_named_params(p(x1,x2,…xl,x##BOOST_PP_INC(l)));
-} 
-  .
-  .
-  .
- 
-template <class A1, class A2, …class Ah>
-r name(
-    A1 const& a1, A2 const& a2, …Ah const& xh
-  , typename p::match<A1,A2,…Ah>::type p = p())
-{
-   return name_with_named_params(p(a1,a2,…ah));
-}
-
-
-
-
-
-

6.2   BOOST_PARAMETER_KEYWORD(n,k)

-

Generates the declaration of a keyword tag type named k in -namespace n, and a corresponding keyword object definition in -the enclosing namespace.

- --- - - - -
Defined in:boost/parameter/keyword.hpp
-
-
Generates
-
-namespace n { struct k; }
-namespace { 
-  boost::parameter::keyword<tag-namespace::k>& k
-  = boost::parameter::keyword<tag-namespace::k>::get();
-}
-
-
-
-
-
-

6.3   BOOST_PARAMETER_MATCH(p,a,x)

-

Generates a defaulted parameter declaration for a forwarding -function.

- --- - - - -
Defined in:boost/parameter/match.hpp
- --- - - - -
Requires:

a is a Boost.Preprocessor sequence -of the form

-
-(A0)(A1)…(An)
-
-
-
-
Generates
-
-typename p::match<A0,A1…,An>::type x = p()
-
-
-
-
-
-
-

7   Configuration Macros

-
-

7.1   BOOST_PARAMETER_MAX_ARITY

-

Determines the maximum number of arguments supported by the -library. Will only be #defined by the library if it is not -already #defined.

- --- - - - -
Defined in:boost/parameter/config.hpp
- --- - - - -
Default Value:5
-
-
-
-

8   Tutorial

-

Follow this link to the Boost.Parameter tutorial -documentation.

-
- - - - - -
[1]References to tag objects may be initialized multiple -times. This scenario can only occur in the presence of -threading. Because the C++ standard doesn't consider threading, -it doesn't explicitly allow or forbid multiple initialization of -references. That said, it's hard to imagine an implementation -where it could make a difference.
- - - - - -
[2](1, 2) Where BOOST_NO_RESULT_OF is #defined, -boost::result_of<F()>::type is replaced by -F::result_type.
-
-
- - - - diff --git a/doc/html/rst.css b/doc/html/rst.css deleted file mode 100755 index c9b14aa..0000000 --- a/doc/html/rst.css +++ /dev/null @@ -1,34 +0,0 @@ -@import "../../../../rst.css"; - -div.section div.section div.section dl { - margin-left: 2em; -} - -td span { - vertical-align: text-top; -} - -img { - border: none; - vertical-align: middle -} - -span.vellipsis { - line-height: 30% ; - font-size: 200% ; -} - - -PRE -{ - FONT-FAMILY: monospace ; -} - -CODE -{ - FONT-FAMILY: monospace; -} -.pre -{ - FONT-FAMILY: monospace; -} diff --git a/doc/index.rst b/doc/index.rst deleted file mode 100755 index 871da0e..0000000 --- a/doc/index.rst +++ /dev/null @@ -1,1275 +0,0 @@ -+++++++++++++++++++++++++++++++++++++++++++++++++ - The Boost Parameter Library -+++++++++++++++++++++++++++++++++++++++++++++++++ - -|(logo)|__ - -.. |(logo)| image:: ../../../../boost.png - :alt: Boost - -__ ../../../../index.htm - -------------------------------------- - -:Abstract: Use this library to write functions that accept - arguments by name: - - .. parsed-literal:: - - new_window("alert", **width=10**, **titlebar=false**); - - Since named arguments can be passed in any order, they are - especially useful when a function has more than one parameter - with a useful default value. - -------------------------------------- - -:Authors: David Abrahams, Daniel Wallin -:Contact: dave@boost-consulting.com, dalwan01@student.umu.se -:Organization: `Boost Consulting`_ -:Date: $Date: 2005/07/18 20:34:31 $ - -:Copyright: Copyright David Abrahams, Daniel Wallin - 2005. Distributed under the Boost Software License, - Version 1.0. (See accompanying file LICENSE_1_0.txt - or copy at http://www.boost.org/LICENSE_1_0.txt) - -.. _`Boost Consulting`: http://www.boost-consulting.com - -.. _concepts: ../../../more/generic_programming.html#concept - -------------------------------------- - -.. contents:: **Table of Contents** - -.. role:: concept - :class: concept - -.. role:: vellipsis - :class: vellipsis - -.. section-numbering:: - -------------------------------------- - -============== - Introduction -============== - -In C++, arguments are normally given meaning by their positions -with respect to a parameter list. That protocol is fine when there -is at most one parameter with a default value, but when there are -even a few useful defaults, the positional interface becomes -burdensome: - -* Since an argument's meaning is given by its position, we have to - choose an (often arbitrary) order for parameters with default - values, making some combinations of defaults unusable: - - .. parsed-literal:: - - window* new_window( - char const* name, - **int border_width = default_border_width,** - bool movable = true, - bool initially_visible = true - ); - - const bool movability = false; - window* w = new_window("alert box", movability); - - In the example above we wanted to make an unmoveable window - with a default ``border_width``, but instead we got a moveable - window with a ``border_width`` of zero. To get the desired - effect, we'd need to write: - - .. parsed-literal:: - - window* w = new_window( - "alert box", **default_border_width**, movability); - - -* It can become difficult for readers to understand the meaning of - arguments at the call site:: - - window* w = new_window("alert", 1, true, false); - - Is this window moveable and initially invisible, or unmoveable - and initially visible? The reader needs to remember the order - of arguments to be sure. - -* The author of the call may not remember the order of the - arguments either, leading to hard-to-find bugs. - -This library addresses the problems outlined above by associating -each parameter with a keyword object. Now users can identify -arguments by keyword, rather than by position: - -.. parsed-literal:: - - window* w = new_window("alert box", **movable=**\ false); // OK! - -.. I'm inclined to leave this part out. In particular, the 2nd - point is kinda lame because even with the library, we need to - introduce overloads -- dwa: - - C++ has two other limitations, with respect to default arguments, - that are unrelated to its positional interface: - - * Default values cannot depend on the values of other function - parameters: - - .. parsed-literal:: - - // Can we make resize windows to a square shape by default? - void resize( - window* w, - int **width**, - int height **= width** // nope, error! - ); - - * Default values in function templates are useless for any - argument whose type should be deduced when the argument is - supplied explicitly:: - - template - void f(T x = 0); - - f(3.14) // ok: x supplied explicitly; T is double - f(); // error: can't deduce T from default argument 0! - - As a side effect of using the Boost Parameter library, you may find - that you circumvent both of these limitations quite naturally. - -========== - Tutorial -========== - -In this section we'll show how the Parameter library can be used to -build an expressive interface to the `Boost Graph library`__\ 's -|dfs|_ algorithm. [#old_interface]_ After laying some groundwork -and describing the algorithm's abstract interface, we'll show you -how to build a basic implementation with keyword support. Then -we'll add support for default arguments and we'll gradually refine the -implementation with syntax improvements. Finally we'll show how to -streamline the implementation of named parameter interfaces, -improve their participation in overload resolution, and optimize -their runtime efficiency. - -__ ../../../graph/index.html - -.. _dfs: ../../../graph/doc/depth_first_search.html - -.. |dfs| replace:: ``depth_first_search`` - - -Headers And Namespaces -====================== - -Most components of the Parameter library are declared in a -header named for the component. For example, :: - - #include - -will ensure ``boost::parameter::keyword`` is known to the -compiler. There is also a combined header, -``boost/parameter.hpp``, that includes most of the library's -components. For the the rest of this tutorial, unless we say -otherwise, you can use the rule above to figure out which header -to ``#include`` to access any given component of the library. - -Also, the examples below will also be written as if the -namespace alias :: - - namespace parameter = boost::parameter; - -has been declared: we'll write ``parameter::xxx`` instead of -``boost::parameter::xxx``. - -The Abstract Interface to |dfs| -=============================== - -The Graph library's |dfs| algorithm is a generic function accepting -from one to four arguments by reference. If all arguments were -required, its signature might be as follows:: - - template < - class Graph, class DFSVisitor, class Index, class ColorMap - > - void depth_first_search( - , Graph const& graph - , DFSVisitor visitor - , typename graph_traits::vertex_descriptor root_vertex - , IndexMap index_map - , ColorMap& color); - -However, most of the parameters have a useful default value, as -shown in the table below. - -.. _`parameter table`: -.. _`default expressions`: - -.. table:: ``depth_first_search`` Parameters - - +----------------+----------+----------------------------------+ - | Parameter Name | Dataflow | Default Value (if any) | - +================+==========+==================================+ - |``graph`` | in |none - this argument is required. | - +----------------+----------+----------------------------------+ - |``visitor`` | in |``boost::dfs_visitor<>()`` | - +----------------+----------+----------------------------------+ - |``root_vertex`` | in |``*vertices(graph).first`` | - +----------------+----------+----------------------------------+ - |``index_map`` | in |``get(boost::vertex_index,graph)``| - +----------------+----------+----------------------------------+ - |``color_map`` | out |an ``iterator_property_map`` | - | | |created from a ``std::vector`` of | - | | |``default_color_type`` of size | - | | |``num_vertices(graph)`` and using | - | | |``index_map`` for the index map. | - +----------------+----------+----------------------------------+ - -Don't be intimidated by the complex default values. For the -purposes of this exercise, you don't need to understand what they -mean. Also, we'll show you how the default for ``color_map`` is -computed later in the tutorial; trust us when we say that the -complexity of its default will become valuable. - -Defining the Keywords -===================== - -The point of this exercise is to make it possible to call -``depth_first_search`` with keyword arguments, leaving out any -arguments for which the default is appropriate: - -.. parsed-literal:: - - graphs::depth_first_search(g, **color_map = my_color_map**); - -To make that syntax legal, there needs to be an object called -``color_map`` with an assignment operator that can accept a -``my_color_map`` argument. In this step we'll create one such -**keyword object** for each parameter. Each keyword object will be -identified by a unique **keyword tag type**. - -We're going to define our interface in namespace ``graphs``. Since -users need access to the keyword objects, but not the tag types, -we'll define the keyword objects so they're acceessible through -``graphs``, and we'll hide the tag types away in a tested -namespace, ``graphs::tag``. The library provides a convenient -macro for that purpose (MSVC6.x users see this note__):: - - #include - - namespace graphs - { - BOOST_PARAMETER_KEYWORD(tag, graph) // Note: no semicolon - BOOST_PARAMETER_KEYWORD(tag, visitor) - BOOST_PARAMETER_KEYWORD(tag, root_vertex) - BOOST_PARAMETER_KEYWORD(tag, index_map) - BOOST_PARAMETER_KEYWORD(tag, color_map) - } - -__ `Compiler Can't See References In Unnamed Namespace`_ - -The declaration of the ``visitor`` keyword you see here is -equivalent to:: - - namespace graphs - { - namespace tag { struct visitor; } - namespace { - boost::parameter::keyword& visitor - = boost::parameter::keyword::get(); - } - } - -This “fancy dance” involving the unnamed namespace and references -is all done to avoid violating the One Definition Rule (ODR) -[#odr]_ when the named parameter interface is used by function -templates that are instantiated in multiple translation -units. - -Defining the Implementation Function -==================================== - -Next we can write the skeleton of the function that implements -the core of ``depth_first_search``:: - - namespace graphs { namespace core - { - template - void depth_first_search(ArgumentPack const& args) - { - // algorithm implementation goes here - } - }} - -.. |ArgumentPack| replace:: :concept:`ArgumentPack` - -``core::depth_first_search`` has an |ArgumentPack| -parameter: a bundle of references to the arguments that the caller -passes to the algorithm, tagged with their keywords. To extract -each parameter, just pass its keyword object to the -|ArgumentPack|\ 's subscript operator. Just to get a feel for how -things work, let's add some temporary code to print the arguments: - -.. parsed-literal:: - - namespace graphs { namespace core - { - template - void depth_first_search(ArgumentPack const& args) - { - std::cout << "graph:\\t" << **args[graph]** << std::endl; - std::cout << "visitor:\\t" << **args[visitor]** << std::endl; - std::cout << "root_vertex:\\t" << **args[root_vertex]** << std::endl; - std::cout << "index_map:\\t" << **args[index_map]** << std::endl; - std::cout << "color_map:\\t" << **args[color_map]** << std::endl; - } - }} // graphs::core - -It's unlikely that many of the arguments the caller will eventually -pass to ``depth_first_search`` can be printed, but for now the code -above will give us something to experiment with. To see the -keywords in action, we can write a little test driver: - -.. parsed-literal:: - - int main() - { - using namespace graphs; - - core::depth_first_search(**(** - graph = 'G', visitor = 2, root_vertex = 3.5, - index_map = "hello, world", color_map = false\ **)**); - } - -An overloaded comma operator (``operator,``) combines the results -of assigning to each keyword object into a single |ArgumentPack| -object that gets passed on to ``core::depth_first_search``. The -extra set of parentheses you see in the example above are required: -without them, each assignment would be interpreted as a separate -function argument and the comma operator wouldn't take effect. -We'll show you how to get rid of the extra parentheses later in -this tutorial. - -Of course, we can pass the arguments in any order:: - - int main() - { - using namespace graphs; - - core::depth_first_search(( - root_vertex = 3.5, graph = 'G', color_map = false, - index_map = "hello, world", visitor = 2)); - } - -either of the two programs above will print:: - - graph: G - visitor: 2 - root_vertex: 3.5 - index_map: hello, world - color_map: false - -Adding Defaults -=============== - -Currently, all the arguments to ``depth_first_search`` are -required. If any parameter can't be found, there will be a -compilation error where we try to extract it from the -|ArgumentPack| using the subscript operator. To make it -legal to omit an argument we need to give it a default value. - -Syntax ------- - -We can make any of the parameters optional by following its keyword -with the ``|`` operator and the parameter's default value within -the square brackets. In the following example, we've given -``root_vertex`` a default of ``42`` and ``color_map`` a default of -``"hello, world"``. - -.. parsed-literal:: - - namespace graphs { namespace core - { - template - void depth_first_search(ArgumentPack const& args) - { - std::cout << "graph:\\t" << args[graph] << std::endl; - std::cout << "visitor:\\t" << args[visitor] << std::endl; - std::cout << "root_vertex:\\t" << args[root_vertex\ **|42**\ ] << std::endl; - std::cout << "index_map:\\t" << args[index_map] << std::endl; - std::cout << "color_map:\\t" << args[color_map\ **|"hello, world"**\ ] << std::endl; - } - }} // graphs::core - -Now we can invoke the function without supplying ``color_map`` or -``root_vertex``:: - - core::depth_first_search(( - graph = 'G', index_map = "index", visitor = 6)); - -The call above would print:: - - graph: G - visitor: 6 - root_vertex: 42 - index_map: index - color_map: hello, world - -.. Important:: - - The index expression ``args[…]`` always yields a *reference* - that is bound either to the actual argument passed by the caller - or, if no argument is passed explicitly, to the specified - default value. - -Getting More Realistic ----------------------- - -Now it's time to put some more realistic defaults in place. We'll -have to give up our print statements—at least if we want to see the -defaults work—since, the default values of these -parameters generally aren't printable. - -Instead, we'll connect local variables to the arguments and use -those in our algorithm: - -.. parsed-literal:: - - namespace graphs { namespace core - { - template - void depth_first_search(ArgumentPack const& args) - { - *Graph* g = args[graph]; - *Visitor* v = args[visitor|\ *default-expression*\ :sub:`1`\ ]; - *Vertex* s = args[root_vertex|\ *default-expression*\ :sub:`2`\ ]; - *Index* i = args[index_map|\ *default-expression*\ :sub:`3`\ ]; - *Color* c = args[visitor|\ *default-expression*\ :sub:`4`\ ]; - - *…use g, v, s, i, and c to implement the algorithm…* - } - }} // graphs::core - -We'll insert the `default expressions`_ in a moment, but first we -need to come up with the types *Graph*, *Visitor*, *Vertex*, -*Index*, and *Color*. - -The ``binding`` |Metafunction|_ -------------------------------- - -To compute the type of a parameter we can use a |Metafunction|_ -called ``binding``: - -.. parsed-literal:: - - binding - { typedef *see text* type; }; - -where ``Default`` is the type of the default argument, if any. - -For example, to declare and initialize ``g`` above, we could write: - -.. parsed-literal:: - - typedef typename parameter::binding< - ArgumentPack,\ **tag::graph** - >::type Graph; - - Graph g = args[graph]; - -As shown in the `parameter table`_, ``graph`` has no default, so -the ``binding`` invocation for *Graph* takes only two arguments. -The default ``visitor`` is ``boost::dfs_visitor<>()``, so the -``binding`` invocation for *Visitor* takes three arguments: - -.. parsed-literal:: - - typedef typename parameter::binding< - ArgumentPack,\ **tag::visitor,boost::dfs_visitor<>** - >::type Visitor; - - Visitor v = args[visitor|\ **boost::dfs_visitor<>()**\ ]; - -Note that the default ``visitor`` is supplied as a *temporary* -instance of ``dfs_visitor``. Because ``args[…]`` always yields -a reference, making ``v`` a reference would cause it to bind to -that temporary, and immediately dangle. Therefore, it's crucial -that we passed ``dfs_visitor<>``, and not ``dfs_visitor<> -const&``, as the last argument to ``binding``. - -.. Important:: - - Never pass ``binding`` a reference type as the default unless - you know that the default value passed to the |ArgumentPack|\ 's - indexing operator will outlive the reference you'll bind to it. - -Sometimes there's no need to use ``binding`` at all. The -``root_vertex`` argument is required to be of the graph's -``vertex_descriptor`` type, [#vertex_descriptor]_ so we can just -use that knowledge to bypass ``binding`` altogether. - -.. parsed-literal:: - - typename **boost::graph_traits::vertex_descriptor** - s = args[root_vertex|\ ***vertices(g).first**\ ]; - -.. _dangling: - -.. |Metafunction| replace:: :concept:`Metafunction` - -.. _Metafunction: ../../../mpl/doc/refmanual/metafunction.html - -Beyond Ordinary Default Arguments ---------------------------------- - -Here's how you might write the declaration for the ``index_map`` -parameter: - -.. parsed-literal:: - - typedef typename parameter::binding< - ArgumentPack - , tag::index_map - , **typename boost::property_map::const_type** - >::type Index; - - Index i = args[index_map|\ **get(boost::vertex_index,g)**\ ]; - -Notice two capabilities we've gained over what -plain C++ default arguments provide: - -1. The default value of the ``index`` parameter depends on the - value of the ``graph`` parameter. That's illegal in plain C++: - - .. parsed-literal:: - - void f(int **graph**, int index = **graph** + 1); // error - -2. The ``index`` parameter has a useful default, yet it is - templated and its type can be deduced when an ``index`` - argument is explicitly specified by the caller. In plain C++, you - can *specify* a default value for a parameter with deduced type, - but it's not very useful: - - .. parsed-literal:: - - template - int f(Index index **= 42**); // OK - int y = f(); // **error; can't deduce Index** - -Syntactic Refinement -==================== - -In this section we'll describe how you can allow callers to invoke -``depth_first_search`` with just one pair of parentheses, and to -omit keywords where appropriate. - - -Describing the Positional Argument Order ----------------------------------------- - -.. _ParameterSpec: - -.. |ParameterSpec| replace:: :concept:`ParameterSpec` - -First, we'll need to build a type that describes the allowed -parameters and their ordering when passed positionally. This type -is known as a |ParameterSpec| (MSVC6.x users see this note__):: - - namespace graphs - { - typedef parameter::parameters< - tag::graph - , tag::visitor - , tag::root_vertex - , tag::index_map - , tag::color_map - > dfs_params; - } - -__ `Can't Declare ParameterSpec Via typedef`_ - -The ``parameters`` template supplies a function-call -operator that groups all its arguments into an |ArgumentPack|. Any -arguments passed to it without a keyword label will be associated -with a parameter according to its position in the |ParameterSpec|. -So for example, given an object ``p`` of type ``dfs_params``, :: - - p('G', index_map=1) - -yields an |ArgumentPack| whose ``graph`` parameter has a value of -``'G'``, and whose ``index_map`` parameter has a value of ``1``. - -Forwarding Functions --------------------- - -Next we need a family of overloaded ``depth_first_search`` function -templates that can be called with anywhere from one to five -arguments. These *forwarding functions* will invoke an instance of -``dfs_params`` as a function object, passing their parameters -to its ``operator()`` and forwarding the result on to -``core::depth_first_search``: - -.. parsed-literal:: - - namespace graphs - { - template - void depth_first_search(A0 const& a0) - { - core::depth_first_search(dfs_params()(a0)); - } - - template - void depth_first_search(A0 const& a0, A1 const& a1) - { - core::depth_first_search(dfs_params()(a0,a1)); - } :vellipsis:`\ - . - . - . -  ` - template - void depth_first_search(A0 const& a0, A1 const& a1, …A4 const& a4) - { - core::depth_first_search(dfs_params()(a0,a1,a2,a3,a4)); - } - } - -That's it! We can now call ``graphs::depth_first_search`` with -from one to five arguments passed positionally or via keyword. - -“Out” Parameters ----------------- - -Well, that's not *quite* it. When passing arguments by keyword, -the keyword object's assignment operator yields a temporary -|ArgumentPack| object. A conforming C++ compiler will refuse to -bind a non-``const`` reference to a temporary, so to support a -keyword interface for all arguments, the overload set above *must* -take its arguments by ``const`` reference. On the other hand—as -you may recall from the `parameter table`_\ —\ ``color_map`` is an -“out” parameter, so it really should be passed by *non-*\ ``const`` -reference. - -A keyword object has a pair of ``operator=`` overloads that ensure -we can pass anything—temporary or not, ``const`` or not—by name, -while preserving the mutability of non-temporaries: - -.. parsed-literal:: - - template // handles non-const, - |ArgumentPack| operator=(A&); // non-temporary objects - - template // handles const objects - |ArgumentPack| operator=(A const&); // and temporaries - -However, when an “out” parameter is passed positionally, there's no -keyword object involved. With our ``depth_first_search`` overload -set above, the ``color_map`` will be passed by ``const`` reference, -and compilation will fail when mutating operations are used on it. -The simple solution is to add another overload that takes a -non-``const`` reference in the position of the “out” parameter: - -.. parsed-literal:: - - template - void depth_first_search(A0 **const&** a0, A1 **const&** a1, …\ A4\ **&** a4) - { - core::depth_first_search(dfs_params()(a0,a1,a2,a3,a4)); - } - -That approach works nicely because there is only one “out” -parameter and it is in the last position. If ``color_map`` had -been the first parameter, we would have needed *ten* overloads. In -the worst case—where the function has five “out” parameters—2\ -:sup:`5` or 32 overloads would be required. This “\ `forwarding -problem`_\ ” is well-known to generic library authors, and the C++ -standard committee is working on a proposal__ to address it. In -the meantime, you might consider using `Boost.Preprocessor`_ to -generate the overloads you need. - -.. _`forwarding problem`: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1385.htm - -__ http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1690.html - -.. _`Boost.Preprocessor`: ../../../preprocessor - -If it is impractical for you to generate or write the overloads -that would be required for positional “out” arguments to be passed -directly, you still have the option to ask users to pass them -through |ref|_, which will ensure that the algorithm implementation -sees a non-``const`` reference: - -.. parsed-literal:: - - depth_first_search(g, v, s, i, **boost::ref(c)**); - -.. |ref| replace:: ``boost::ref`` - -.. _ref: http://www.boost.org/doc/html/reference_wrapper.html - -Generating Forwarding Functions with Macros -------------------------------------------- - -To remove some of the tedium of writing overloaded forwarding -functions, the library supplies a macro, suitably located in -``boost/parameter/macros.hpp``, that will generate free function -overloads for you:: - - BOOST_PARAMETER_FUN(void, depth_first_search, 1, 5, dfs_params); - -will generate a family of five ``depth_first_search`` overloads, in -the current scope, that pass their arguments through -``dfs_params``. Instead of ``core::depth_first_search``, these -overloads will forward the |ArgumentPack| on to a function called -``depth_first_search_with_named_params``, also in the current -scope. It's up to you to implement that function. You could -simply transplant the body of ``core::depth_first_search`` into -``depth_first_search_with_named_params`` if you were going to use -this approach. - -Note that ``BOOST_PARAMETER_FUN`` only takes arguments by ``const`` -reference, so you will have to add any additional overloads -required to handle positional “out” parameters yourself. We are -looking into providing a more sophisticated set of macros to -address this problem and others, for an upcoming release of Boost. - -Controlling Overload Resolution -=============================== - -The parameters of our templated forwarding functions are completely -general; in fact, they're a perfect match for any argument type -whatsoever. The problems with exposing such general function -templates have been the subject of much discussion, especially in -the presence of `unqualified calls`__. Probably the safest thing -to do is to isolate the forwarding functions in a namespace -containing no types [#using]_, but often we'd *like* our functions -to play nicely with argument-dependent lookup and other function -overloads. In that case, it's neccessary to remove the functions -from the overload set when the passed argument types aren't -appropriate. - -__ http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-defects.html#225 - -Updating the |ParameterSpec| ----------------------------- - -This sort of overload control can be accomplished in C++ by taking -advantage of the SFINAE (Substitution Failure Is Not An Error) -rule. [#sfinae]_ You can take advantage of the Parameter library's -built-in SFINAE support by using the following class templates in -your |ParameterSpec|: - -.. parsed-literal:: - - template< class KeywordTag, class Predicate = *unspecified* > - struct required; - - template< class KeywordTag, class Predicate = *unspecified* > - struct optional; - -Instead of using keyword tags directly, we can wrap them in -``required`` and ``optional`` to indicate which function parameters -are required, and optionally pass ``Predicate``\ s to describe the -type requirements for each function parameter. The ``Predicate`` -argument must be a unary `MPL lambda expression`_ that, when -applied to the actual type of the argument, indicates whether that -argument type meets the function's requirements for that parameter -position. - -.. _`MPL lambda expression`: ../../../mpl/doc/refmanual/lambda-expression.html - -For example, let's say we want to restrict ``depth_first_search()`` so that -the ``graph`` parameter is required and the ``root_vertex`` -parameter is convertible to ``int``. We might write: - -.. parsed-literal:: - - #include - #include - namespace graphs - { - using namespace boost::mpl::placeholders; - - struct dfs_params - : parameter::parameters< - **parameter::required** - , parameter::optional - , **parameter::optional< - tag::root_vertex, boost::is_convertible<_,int> - >** - , parameter::optional - , parameter::optional - > - {}; - } - -Applying SFINAE to the Overload Set ------------------------------------ - -Now we add a special defaulted argument to each of our -``depth_first_search`` overloads: - -.. parsed-literal:: - - namespace graphs - { - template - void depth_first_search( - A0 const& a0 - , typename dfs_params::match::type p = dfs_params()) - { - core::depth_first_search(**p**\ (a0)); - } - - template - void depth_first_search( - A0 const& a0, A1 const& a1 - , typename dfs_params::match::type p = dfs_params()) - { - core::depth_first_search(**p**\ (a0,a1)); - } :vellipsis:`\ - . - . - . -  ` - template - void depth_first_search( - A0 const& a0, A1 const& a1, …A4 const& A4 - , typename dfs_params::match::type p = dfs_params()) - { - core::depth_first_search(**p**\ (a0,a1,a2,a3,a4)); - } - } - - -These additional parameters are not intended to be used directly -by callers; they merely trigger SFINAE by becoming illegal types -when the ``name`` argument is not convertible to ``const -char*``. The ``BOOST_PARAMETER_FUN`` macro described earlier -adds these extra function parameters for you (Borland users see -this note__). - -.. _BOOST_PARAMETER_MATCH: - -__ `Default Arguments Unsupported on Nested Templates`_ - -Reducing Boilerplate With Macros --------------------------------- - -The library provides a macro you can use to eliminate some of the -repetetiveness of the declaring the optional parameters. -``BOOST_PARAMETER_MATCH`` takes three arguments: the -|ParameterSpec|, a `Boost.Preprocessor sequence`__ of the function -argument types, and a name for the defaulted function parameter -(``p``, above), and it generates the appropriate defaulted -argument. So we could shorten the overload set definition as -follows: - -__ http://boost-consulting.com/mplbook/preprocessor.html#sequences - -.. parsed-literal:: - - namespace graphs - { - template - void depth_first_search( - A0 const& a0 - , **BOOST_PARAMETER_MATCH(dfs_params, (A0), p)**) - { - core::depth_first_search(p(a0)); - } - - template - void depth_first_search( - A0 const& a0, A1 const& a1 - , **BOOST_PARAMETER_MATCH(dfs_params, (A0)(A1), p)**) - { - core::depth_first_search(p(a0,a1)); - } :vellipsis:`\ - . - . - . -  ` - template - void depth_first_search( - A0 const& a0, A1 const& a1, …A4 const& A4 - , **BOOST_PARAMETER_MATCH(dfs_params, (A0)(A1)…(A4), p)**) - { - core::depth_first_search(p(a0,a1,a2,a3,a4)); - } - } - -Efficiency Issues -================= - -The ``color_map`` parameter gives us a few efficiency issues to -consider. Here's a first cut at extraction and binding: - -.. parsed-literal:: - - typedef - vector_property_map - default_color_map; - - typename parameter::binding< - ArgumentPack - , tag::color_map - , default_color_map - >::type color = args[color_map|\ **default_color_map(num_vertices(g),i)**\ ]; - -Eliminating Copies ------------------- - -The library has no way to know whether an explicitly-supplied -argument is expensive to copy (or even if it is copyable at all), -so ``binding<…,k,…>::type`` is always a reference type when the -*k* parameter is supplied by the caller. Since ``args[…]`` -yields a reference to the actual argument, ``color`` will be bound -to the actual ``color_map`` argument and no copying will be done. - -As described above__, because the default is a temporary, it's -important that ``color`` be a non-reference when the default is -used. In that case, the default value will be *copied* into -``color``. If we store the default in a named variable, though, -``color`` can be a reference, thereby eliminating the copy: - -.. parsed-literal:: - - default_color_map default_color(num_vertices(g),i); - - typename parameter::binding< - ArgumentPack - , tag::color_map - , **default_color_map&** - >::type color = args[color_map|default_color]; - -__ dangling_ - -.. Hint:: - - To avoid making needless copies, pass a *reference to the - default type* as the third argument to ``binding``. - -Lazy Default Computation ------------------------- - -Of course it's nice to avoid copying ``default_color``, but the -more important cost is that of *constructing* it in the first -place. A ``vector_property_map`` is cheap to copy, since it holds -its elements via a |shared_ptr|_. On the other hand, construction of -``default_color`` costs at least two dynamic memory allocations and -``num_vertices(g)`` copies; it would be better to avoid doing this -work when the default value won't be needed. - -.. |shared_ptr| replace:: ``shared_ptr`` - -.. _shared_ptr: ../../../smart_ptr/shared_ptr.htm - -To that end, the library allows us to supply a callable object -that—if no argument was supplied by the caller—will be invoked to -construct the default value. Instead of following the keyword with -the ``|`` operator, we'll use ``||`` and follow it with a -nullary (zero-argument) function object that constructs a -default_color_map. Here, we build the function object using -Boost.Lambda_: [#bind]_ - -.. _Boost.Lambda: ../../../lambda/index.html - -.. parsed-literal:: - - // After #include - typename parameter::binding< - ArgumentPack - , tag::color_map - , default_color_map - >::type color = args[ - color_map - **|| boost::lambda::construct(num_vertices(g),i)** - ]; - -.. sidebar:: Mnemonics - - To remember the difference between ``|`` and ``||``, recall that - ``||`` normally uses short-circuit evaluation: its second - argument is only evaluated if its first argument is ``false``. - Similarly, in ``color_map[param||f]``, ``f`` is only invoked if - no ``color_map`` argument was supplied. - -Default Forwarding ------------------- - -Types that are expensive to construct yet cheap to copy aren't all -that typical, and even copying the color map is more expensive than -we might like. It might be nice to avoid both needless -construction *and* needless copying of the default color map. The -simplest way to achieve that is to avoid naming it altogether, at -least not in ``core::depth_first_search``. Instead, we'll -introduce another function template to implement the actual -algorithm: - -.. parsed-literal:: - - namespace graphs { namespace core - { - template - void **dfs_impl**\ (G& g, V& v, S& s, I& i, C& c) - { - *…actual algorithm implementation…* - } - }} - -Then, in ``core::depth_first_search``, we'll simply forward the -result of indexing ``args`` to ``core::dfs_impl``:: - - core::dfs_impl( - g,v,s,i - , args[ - color_map - || boost::lambda::construct(num_vertices(g),i) - ]); - -In real code, after going to the trouble to write ``dfs_impl``, -we'd probably just forward all the arguments. - -Dispatching Based on the Presence of a Default ----------------------------------------------- - -In fact, the Graph library itself constructs a slightly different -``color_map``, to avoid even the overhead of initializing a -|shared_ptr|_:: - - std::vector - color_vec(num_vertices(g)); - - boost::iterator_property_map< - typename std::vector< - boost::default_color_type - >::iterator - , Index - > c(color_vec.begin(), i); - -To avoid instantiating that code when it isn't needed, we'll have -to find a way to select different function implementations, at -compile time, based on whether a ``color_map`` argument was -supplied. By using `tag dispatching`_ on the presence of a -``color_map`` argument, we can do just that: - -.. _`tag dispatching`: ../../../../more/generic_programming.html#tag_dispatching - -.. parsed-literal:: - - #include - #include - - namespace graphs { namespace core { - - template - void dfs_dispatch(ArgumentPack& args, **mpl::true_**) - { - *…use the color map computed in the previous example…* - } - - template - void dfs_dispatch(ArgumentPack& args, **mpl::false_**) - { - *…use args[color]…* - } - - template - void depth_first_search(ArgumentPack& args) - { - typedef typename binding::type color\_; - core::dfs_dispatch(args, **boost::is_same()**\ ); - } - }} - -We've used the fact that the default for ``binding``\ 's third -argument is ``void``: because specializations of ``is_same`` are -``bool``-valued MPL |Integral Constant|_\ s derived either -from ``mpl::true_`` or ``mpl::false_``, the appropriate -``dfs_dispatch`` implementation will be selected. - -.. |Integral Constant| replace:: :concept:`Integral Constant` - -.. _`Integral Constant`: ../../../mpl/doc/refmanual/integral-constant.html - -============================ - Portability Considerations -============================ - -Use the `regression test results`_ for the latest Boost release of -the Parameter library to see how it fares on your favorite -compiler. Additionally, you may need to be aware of the following -issues and workarounds for particular compilers. - -.. _`regression test results`: http://www.boost.org/regression/release/user/parameter.html - -No SFINAE Support -================= - -Some older compilers don't support SFINAE. If your compiler meets -that criterion, then Boost headers will ``#define`` the preprocessor -symbol ``BOOST_NO_SFINAE``, and uses of ``parameters<…>::match`` and -|BOOST_PARAMETER_MATCH| will be harmless, but will have no effect. - -No Support for |result_of|_ -=========================== - -.. |result_of| replace:: ``result_of`` - -.. _result_of: ../../../utility/utility.htm#result_of - -`Lazy default computation`_ relies on the |result_of| class -template to compute the types of default arguments given the type -of the function object that constructs them. On compilers that -don't support |result_of|, ``BOOST_NO_RESULT_OF`` will be -``#define``\ d, and the compiler will expect the function object to -contain a nested type name, ``result_type``, that indicates its -return type when invoked without arguments. To use an ordinary -function as a default generator on those compilers, you'll need to -wrap it in a class that provides ``result_type`` as a ``typedef`` -and invokes the function via its ``operator()``. - -Can't Declare |ParameterSpec| via ``typedef`` -============================================= - -In principle you can declare a |ParameterSpec| as a ``typedef`` -for a specialization of ``parameters<…>``, but Microsoft Visual C++ -6.x has been seen to choke on that usage. The workaround is to use -inheritance and declare your |ParameterSpec| as a class: - -.. parsed-literal:: - - **struct dfs_parameters - :** parameter::parameters< - tag::graph, tag::visitor, tag::root_vertex - , tag::index_map, tag::color_map - > **{};** - -Default Arguments Unsupported on Nested Templates -================================================= - -As of this writing, Borland compilers don't support the use of -default template arguments on member class templates. As a result, -you have to supply ``BOOST_PARAMETER_MAX_ARITY`` arguments to every -use of ``parameters<…>::match``. Since the actual defaults used -are unspecified, the workaround is to use -|BOOST_PARAMETER_MATCH|_ to declare default arguments for SFINAE. - -.. |BOOST_PARAMETER_MATCH| replace:: ``BOOST_PARAMETER_MATCH`` - -Compiler Can't See References In Unnamed Namespace -================================================== - -If you use Microsoft Visual C++ 6.x, you may find that the compiler -has trouble finding your keyword objects. This problem has been -observed, but only on this one compiler, and it disappeared as the -test code evolved, so we suggest you use it only as a last resort -rather than as a preventative measure. The solution is to add -*using-declarations* to force the names to be available in the -enclosing namespace without qualification:: - - namespace graphs - { - using graphs::graph; - using graphs::visitor; - using graphs::root_vertex; - using graphs::index_map; - using graphs::color_map; - } - -=========== - Reference -=========== - -.. _reference: reference.html - -Follow `this link`__ to the Boost.Parameter reference -documentation. - -__ reference.html - -================== - Acknowledgements -================== - -The authors would like to thank all the Boosters who participated -in the review of this library and its documentation, most -especially our review manager, Doug Gregor. - --------------------------- - -.. [#old_interface] As of Boost 1.33.0 the Graph library was still - using an `older named parameter mechanism`__, but there are - plans to change it to use Boost.Parameter (this library) in an - upcoming release, while keeping the old interface available for - backward-compatibility. - -__ ../../../graph/doc/bgl_named_params.html - -.. [#odr] The **One Definition Rule** says that any given entity in - a C++ program must have the same definition in all translation - units (object files) that make up a program. - -.. [#vertex_descriptor] If you're not familiar with the Boost Graph - Library, don't worry about the meaning of any - Graph-library-specific details you encounter. In this case you - could replace all mentions of vertex descriptor types with - ``int`` in the text, and your understanding of the Parameter - library wouldn't suffer. - -.. [#bind] The Lambda library is known not to work on `some - less-conformant compilers`__. When using one of those you could - define :: - - template - struct construct2 - { - typedef T result_type; - - template - T operator()(A1 a1, A2 a2) { return T(a1,a2); } - }; - - and use `Boost.Bind`_ to generate the function object:: - - boost::bind(construct2(),num_vertices(g),i) - -__ http://www.boost.org/regression/release/user/lambda.html -.. _Boost.Bind: ../../../libs/bind/index.html - - -.. [#using] You can always give the illusion that the function - lives in an outer namespace by applying a *using-declaration*:: - - namespace foo_overloads - { - // foo declarations here - void foo() { ... } - ... - } - using foo_overloads::foo; - - -.. [#sfinae] If type substitution during the instantiation of a - function template results in an invalid type, no compilation - error is emitted; instead the overload is removed from the - overload set. By producing an invalid type in the function - signature depending on the result of some condition, whether or - not an overload is considered during overload resolution can be - controlled. The technique is formalized in the |enable_if|_ - utility. See - http://www.semantics.org/once_weakly/w02_SFINAE.pdf for more - information on SFINAE. - -.. |enable_if| replace:: ``enable_if`` -.. _enable_if: ../../../utility/enable_if.html - - diff --git a/doc/reference.rst b/doc/reference.rst deleted file mode 100755 index 20b6f13..0000000 --- a/doc/reference.rst +++ /dev/null @@ -1,689 +0,0 @@ -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - The Boost Parameter Library Reference Documentation -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -|(logo)|__ - -.. |(logo)| image:: ../../../../boost.png - :alt: Boost - -__ ../../../../index.htm - -:Authors: David Abrahams, Daniel Wallin -:Contact: dave@boost-consulting.com, dalwan01@student.umu.se -:organization: `Boost Consulting`_ -:date: $Date: 2005/07/17 19:53:01 $ - -:copyright: Copyright David Abrahams, Daniel Wallin - 2005. Distributed under the Boost Software License, - Version 1.0. (See accompanying file LICENSE_1_0.txt - or copy at http://www.boost.org/LICENSE_1_0.txt) - -.. _`Boost Consulting`: http://www.boost-consulting.com - - -////////////////////////////////////////////////////////////////////////////// - -.. contents:: - :depth: 2 - -////////////////////////////////////////////////////////////////////////////// - -.. role:: class - :class: class - -.. role:: concept - :class: concept - -.. role:: function - :class: function - -.. |ArgumentPack| replace:: :concept:`ArgumentPack` -.. |ParameterSpec| replace:: :concept:`ParameterSpec` - -.. role:: vellipsis - :class: vellipsis - -.. section-numbering:: - :depth: 2 - -Preliminaries -============= - -This section covers some basic information you'll need to know in -order to understand this reference - -Namespaces ----------- - -In this document, all unqualified identifiers should be assumed to -be defined in namespace ``boost::parameter`` unless otherwise -specified. - -Exceptions ----------- - -No operation described in this document -throws an exception unless otherwise specified. - -Thread Safety -------------- - -All components of this library can be used safely from multiple -threads without synchronization. [#thread]_ - -Typography ----------- - -Names written in :concept:`sans serif type` represent concepts_. - -In code blocks, *italic type* represents unspecified text that -satisfies the requirements given in the detailed description that -follows the code block. - -In a specification of the tokens generated by a macro, **bold -type** is used to highlight the position of the expanded macro -argument in the result. - -The special character β represents the value of |BOOST_PARAMETER_MAX_ARITY|_. - -////////////////////////////////////////////////////////////////////////////// - -Terminology -=========== - -.. |kw| replace:: keyword -.. _kw: - -keyword - The name of a function parameter. - -.. _keyword tag type: -.. |keyword tag type| replace:: `keyword tag type`_ - -keyword tag type - A type used to uniquely identify a function parameter. Typically - its name will be the same as that of the parameter. - -.. _positional: -.. |positional| replace:: `positional`_ - -positional argument - An argument passed with no explicit |kw|. Its parameter is - determined in the usual C++ way: by position with respect to a - parameter list. - -.. _tag type: -.. |tag type| replace:: `tag type`_ - -tag type - Shorthand for “\ |keyword tag type|.” - -.. _keyword object: -.. |keyword object| replace:: `keyword object`_ - -keyword object - An instance of |keyword|_ ```` for some |tag - type| ``T``. - -.. _tagged reference: -.. |tagged reference| replace:: `tagged reference`_ - -tagged reference - An object whose type is associated with a |keyword tag type| (the - object's *keyword*), and that holds a reference (to the object's - *value*). - - As a shorthand, a “tagged reference to ``x``\ ” means a tagged - reference whose *value* is ``x``. - -.. _tagged default: -.. |tagged default| replace:: `tagged default`_ - -tagged default - A |tagged reference| whose *value* represents the value of a - default argument. - -.. _tagged lazy default: -.. |tagged lazy default| replace:: `tagged lazy default`_ - -tagged lazy default - A |tagged reference| whose *value*, when invoked with no - arguments, computes a default argument value. - -.. _intended argument type: -.. |intended argument type| replace:: `intended argument type`_ - -intended argument type - The *intended argument type* of a single-element |ArgumentPack|_ is the - type of its element's *value*. The intended argument type of any other - type ``X`` is ``X`` itself. - -.. Note:: - - In this reference, we will use concept names (and other names) - to describe both types and objects, depending on context. So - for example, “an |ArgumentPack|_\ ” can refer to a type that - models |ArgumentPack|_ *or* an object of such a type. - -////////////////////////////////////////////////////////////////////////////// - -Concepts -======== - -This section describes the generic type concepts_ used by the Parameter library. - -.. _concepts: ../../../../more/generic_programming.html#concept - -|ArgumentPack| --------------- - -An |ArgumentPack| is a collection of |tagged reference|\ s to the -actual arguments passed to a function. - -Requirements -............ - -In the table below, - -* ``A`` is a model of |ArgumentPack| -* ``x`` is an instance of ``A`` -* ``u`` is a |keyword object| of type ``K`` -* ``v`` is a |tagged default| with |tag type| ``L`` and *value* of type ``D`` -* ``w`` is a |tagged lazy default| with |tag type| ``M`` and *value* of type ``E const`` -* ``z`` is an |ArgumentPack| containing a single element (as created by |keyword|_\ ``<…>::operator=``) - -Any exceptions are thrown from the invocation of ``w``\ 's *value* -will be propagated to the caller. - -.. table:: |ArgumentPack| requirements - - +----------+-----------------------------+------------------+--------------------------------------+ - |Expression| Type |Requirements |Semantics/Notes | - +==========+=============================+==================+======================================+ - |``x[u]`` |``binding::type`` |``x`` contains an |Returns *b*\ 's *value* (by | - | | |element *b* whose |reference). | - | | ||kw|_ is ``K`` | | - +----------+-----------------------------+------------------+--------------------------------------+ - |``x[u]`` |``binding::type`` |*none* |If ``x`` contains an element *b* whose| - | | | ||kw|_ is the same as ``u``\ 's, | - | | | |returns *b*\ 's *value* (by | - | | | |reference). Otherwise, returns ``u``\| - | | | |'s *value*. | - +----------+-----------------------------+------------------+--------------------------------------+ - |``x[w]`` |``lazy_binding::type``|*none* |If ``x`` contains an element *b* whose| - | | | ||kw|_ is the same as ``w``\ 's, | - | | | |returns *b*\ 's *value* (by | - | | | |reference). Otherwise, invokes ``w``\| - | | | |'s *value* and returns the result. | - +----------+-----------------------------+------------------+--------------------------------------+ - |``x, z`` |Model of |ArgumentPack| |*none* |Returns an |ArgumentPack|_ containing | - | | | |all the elements of both ``x`` and | - | | | |``z``. | - +----------+-----------------------------+------------------+--------------------------------------+ - - - -.. _parameterspec: - -|ParameterSpec| ---------------- - -A |ParameterSpec| describes the type requirements for arguments -corresponding to a given |kw|_ and indicates whether the argument -is optional or required. The table below details the allowed forms -and describes their condition for satisfaction by an actual -argument type. In each row, - -.. _conditions: - -* ``K`` is the |ParameterSpec|\ 's |keyword tag type| -* ``A`` is an |intended argument type| associated with ``K``, if any -* ``F`` is a unary `MPL lambda expression`_ - -.. _`MPL lambda expression`: ../../../mpl/doc/refmanual/lambda-expression.html - -.. table:: |ParameterSpec| allowed forms and conditions of satisfaction - - +----------------------+--------------+--------------------------------+ - |Type |``A`` required|Condition ``A`` must satisfy | - +======================+==============+================================+ - ||keyword|_\ ```` |no |*n/a* | - +----------------------+--------------+--------------------------------+ - ||optional|_\ ````|no |``mpl::apply::type::value``| - | | |is ``true``. | - +----------------------+--------------+--------------------------------+ - ||required|_\ ````|yes |``mpl::apply::type::value``| - | | |is ``true``. | - +----------------------+--------------+--------------------------------+ - -The information in a |ParameterSpec| is used to `limit`__ the -arguments that will be matched by `forwarding functions`_. - -__ overloadcontrol_ -.. _overloadcontrol: index.html#controlling-overload-resolution -.. _forwarding functions: index.html#forwarding-functions - - -////////////////////////////////////////////////////////////////////////////// - -Class Templates -=============== - -.. |keyword| replace:: ``keyword`` -.. _keyword: - -``keyword`` ------------ - -The type of every |keyword object| is a specialization of |keyword|. - -:Defined in: `boost/parameter/keyword.hpp`__ - -__ ../../../../boost/parameter/keyword.hpp - -.. parsed-literal:: - - template - struct keyword - { - template |ArgumentPack|_ `operator=`_\(T& value) const; - template |ArgumentPack|_ `operator=`_\(T const& value) const; - - template *tagged default* `operator|`_\(T& x) const; - template *tagged default* `operator|`_\(T const& x) const; - - template *tagged lazy default* `operator||`_\(F const&) const; - - static keyword& get_\(); - }; - - -.. |operator=| replace:: ``operator=`` -.. _operator=: - -``operator=`` - .. parsed-literal:: - - template |ArgumentPack|_ operator=(T& value) const; - template |ArgumentPack|_ operator=(T const& value) const; - - :Requires: nothing - - :Returns: - an |ArgumentPack|_ containing a single |tagged reference| to - ``value`` with |kw|_ ``Tag`` - -.. _operator|: - -``operator|`` - .. parsed-literal:: - - template *tagged default* operator|(T& x) const; - template *tagged default* operator|(T const& x) const; - - :Returns: a |tagged default| with *value* ``x`` and |kw|_ ``Tag``. - -.. _operator||: - -``operator||`` - .. parsed-literal:: - - template *tagged lazy default* operator||(F const& g) const; - - :Requires: ``g()`` is valid, with type ``boost::``\ |result_of|_\ - ``::type``. [#no_result_of]_ - - - :Returns: a |tagged lazy default| with *value* ``g`` and |kw|_ ``Tag``. - -.. _get: - -``get`` - .. parsed-literal:: - - static keyword& get\(); - - :Returns: a “singleton instance”: the same object will be - returned on each invocation of ``get()``. - - :Thread Safety: ``get()`` can be called from multiple threads - simultaneously. - -``parameters`` --------------- - -Provides an interface for assembling the actual arguments to a -`forwarding function` into an |ArgumentPack|, in which any -|positional| arguments will be tagged according to the -corresponding template argument to ``parameters``. - -.. _forwarding function: `forwarding functions`_ - -:Defined in: `boost/parameter/parameters.hpp`__ - -__ ../../../../boost/parameter/parameters.hpp - -.. parsed-literal:: - - template - struct parameters - { - template - struct `match`_ - { - typedef … type; - }; - - template - |ArgumentPack|_ `operator()`_\(A0 const& a0) const; - - template - |ArgumentPack|_ `operator()`_\(A0 const& a0, A1 const& a1) const; :vellipsis:`\ - . - . - . -  ` - template - |ArgumentPack|_ `operator()`_\(A0 const& a0, A1 const& a1, …A\ β const& a\ β) const; - }; - - -:Requires: ``P0``, ``P1``, … ``P``\ β are models of |ParameterSpec|_. - - -.. Note:: - - In this section, ``R``\ *i* and ``K``\ *i* are defined as - follows, for any argument type ``A``\ *i*: - - - | ``R``\ *i* is ``A``\ *i*\ 's |intended argument type| - | - | if ``A``\ *i* is a result type of ``keyword::``\ |operator=|_ - | then - | ``K``\ *i* is ``T`` - | else - | ``K``\ *i* is ``P``\ *i*\ 's |keyword tag type|. - - -.. _match: - -``match`` - A |Metafunction|_ used to remove a `forwarding function`_ from overload resolution. - - :Returns: if ``P0``, ``P1``, …\ ``P``\ β are *satisfied* (see - below), then ``parameters``. Otherwise, - ``match::type`` is not defined. - - ``P0``, ``P1``, …\ ``P``\ β are **satisfied** if, for - every *j* in 0…β, either: - - * ``P``\ *j* is the *unspecified* default - * **or**, ``P``\ *j* is a specialization of |keyword|_, - - * **or**, ``P``\ *j* is |optional|_ ```` and either - - - ``X`` is not ``K``\ *i* for any *i*, - - **or** ``X`` is some ``K``\ *i* and ``mpl::apply::type::value`` is ``true`` - - * **or**, ``P``\ *j* is |required|_ ````, and - - - ``X`` is some ``K``\ *i*, **and** - - ``mpl::apply::type::value`` is ``true`` - -.. _operator(): - -``operator()`` - .. parsed-literal:: - - template |ArgumentPack|_ operator()(A0 const& a0) const; :vellipsis:`\ - . - . - . -  ` - template |ArgumentPack|_ `operator()`_\(A0 const& a0, …A\ β const& a\ β) const; - - :Returns: - An |ArgumentPack|_ containing, for each ``a``\ *i*, - - - if ``a``\ *i*, is a single-element |ArgumentPack|, its element - - Otherwise, a |tagged reference| with |kw|_ ``K``\ *i* and *value* ``a``\ *i* - - -.. |optional| replace:: ``optional`` -.. |required| replace:: ``required`` - -.. _optional: -.. _required: - -``optional``, ``required`` --------------------------- - -These templates describe the requirements on a function parameter. - -:Defined in: `boost/parameter/parameters.hpp`__ - -__ ../../../../boost/parameter/parameters.hpp - -:Specializations model: |ParameterSpec|_ - -.. parsed-literal:: - - template - struct optional; - - template - struct required; - -The default value of ``Predicate`` is an unspecified |Metafunction|_ that returns -``mpl::true_`` for any argument. - -.. |Metafunction| replace:: :concept:`Metafunction` -.. _Metafunction: ../../../mpl/doc/refmanual/metafunction.html - -////////////////////////////////////////////////////////////////////////////// - -Metafunctions -============= - -A |Metafunction|_ is conceptually a function that operates on, and -returns, C++ types. - -``binding`` ------------ - -Returns the result type of indexing an argument pack with a -|keyword tag type| or with a |tagged default|. - -:Defined n: `boost/parameter/binding.hpp`__ - -__ ../../../../boost/parameter/binding.hpp - -.. parsed-literal:: - - template - struct binding - { - typedef … type; - }; - -:Requires: ``A`` is a model of |ArgumentPack|_. - -:Returns: the reference type of the |tagged reference| in ``A`` - having |keyword tag type| ``K``, if any. If no such |tagged - reference| exists, returns ``D``. - -``lazy_binding`` ----------------- - -Returns the result type of indexing an argument pack with a |tagged -lazy default|. - -:Defined in: - `boost/parameter/binding.hpp`__ - -__ ../../../../boost/parameter/binding.hpp - -.. parsed-literal:: - - template - struct lazy_binding - { - typedef … type; - }; - -:Requires: ``A`` is a model of |ArgumentPack|_. - -:Returns: the reference type of the |tagged reference| in ``A`` - having |keyword tag type| ``K``, if any. If no such |tagged - reference| exists, returns ``boost::``\ |result_of|_\ ``::type``. [#no_result_of]_ - - -////////////////////////////////////////////////////////////////////////////// - -Code Generation Macros -====================== - -Macros in this section can be used to ease the writing of code -using the Parameter libray by eliminating repetitive boilerplate. - -``BOOST_PARAMETER_FUN(r,n,l,h,p)`` ----------------------------------- - -Generates a sequence of `forwarding function`_ templates named -``n``, with arities ranging from ``l`` to ``h`` , returning ``r``, -and using ``p`` to control overload resolution and assign tags to -positional arguments. - -:Defined in: `boost/parameter/macros.hpp`__ - -__ ../../../../boost/parameter/macros.hpp - -:Requires: ``l`` and ``h`` are nonnegative integer tokens such - that ``l`` < ``h`` - -Generates - .. parsed-literal:: - - template - r name( - A1 const& a1, A2 const& a2, …A\ **l** const& x\ **l** - , typename **p**::match::type p = **p**\ ()) - { - return **name**\ _with_named_params(**p**\ (x1,x2,…x\ **l**)); - } - - template - r name( - A1 const& a1, A2 const& a2, …A\ **l** const& x\ **l** - , A\ ##\ BOOST_PP_INC_\ (**l**) const& x\ ##\ BOOST_PP_INC_\ (**l**) - , typename **p**::match::type p = **p**\ ()) - { - return **name**\ _with_named_params(**p**\ (x1,x2,…x\ **l**,x\ ##\ BOOST_PP_INC_\ (**l**))); - } :vellipsis:`\ - . - . - . -  ` - template - r name( - A1 const& a1, A2 const& a2, …A\ **h** const& x\ **h** - , typename **p**::match::type p = **p**\ ()) - { - return **name**\ _with_named_params(**p**\ (a1,a2,…a\ **h**)); - } - - -.. _BOOST_PP_INC: ../../../preprocessor/doc/ref/inc.html - -``BOOST_PARAMETER_KEYWORD(n,k)`` --------------------------------- - -Generates the declaration of a |keyword tag type| named ``k`` in -namespace ``n``, and a corresponding |keyword object| definition in -the enclosing namespace. - -:Defined in: `boost/parameter/keyword.hpp`__ - -__ ../../../../boost/parameter/keyword.hpp - -Generates - .. parsed-literal:: - - namespace **n** { struct **k**; } - namespace { - boost::parameter::keyword<*tag-namespace*::**k**>& **k** - = boost::parameter::keyword<*tag-namespace*::**k**>::get(); - } - -``BOOST_PARAMETER_MATCH(p,a,x)`` --------------------------------- - -Generates a defaulted parameter declaration for a `forwarding -function`_. - -:Defined in: `boost/parameter/match.hpp`__ - -__ ../../../../boost/parameter/match.hpp - -:Requires: ``a`` is a `Boost.Preprocessor sequence`__ - of the form - - .. parsed-literal:: - - (A0)(A1)…(A\ *n*) - -__ http://www.boost.org/libs/preprocessor/doc/data.html - -Generates - .. parsed-literal:: - - typename **p**::match<**A0**\ ,\ **A1**\ …,\ **A**\ *n*>::type **x** = **p**\ () - - -Configuration Macros -==================== - -``BOOST_PARAMETER_MAX_ARITY`` ------------------------------ - -Determines the maximum number of arguments supported by the -library. Will only be ``#defined`` by the library if it is not -already ``#defined``. - -.. |BOOST_PARAMETER_MAX_ARITY| replace:: ``BOOST_PARAMETER_MAX_ARITY`` - -:Defined in: `boost/parameter/config.hpp`__ - -__ ../../../../boost/parameter/config.hpp - -:Default Value: ``5`` - -Tutorial -======== - -Follow `this link`__ to the Boost.Parameter tutorial -documentation. - -__ index.html#tutorial - -////////////////////////////////////////////////////////////// - -.. [#thread] References to tag objects may be initialized multiple - times. This scenario can only occur in the presence of - threading. Because the C++ standard doesn't consider threading, - it doesn't explicitly allow or forbid multiple initialization of - references. That said, it's hard to imagine an implementation - where it could make a difference. - -.. [#no_result_of] Where |BOOST_NO_RESULT_OF|_ is ``#defined``, - ``boost::``\ |result_of|_\ ``::type`` is replaced by - ``F::result_type``. - -.. |result_of| replace:: ``result_of`` -.. _result_of: ../../../utility/utility.htm#result_of - -.. |BOOST_NO_RESULT_OF| replace:: ``BOOST_NO_RESULT_OF`` -.. _BOOST_NO_RESULT_OF: ../../../utility/utility.htm#BOOST_NO_RESULT_OF \ No newline at end of file diff --git a/index.html b/index.html deleted file mode 100755 index 672aaab..0000000 --- a/index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - -Automatically loading index page... if nothing happens, please go to -doc/html/index.html. - - diff --git a/test/Jamfile b/test/Jamfile deleted file mode 100755 index 3dfb58b..0000000 --- a/test/Jamfile +++ /dev/null @@ -1,15 +0,0 @@ -# Boost Parameter Library test Jamfile - -subproject libs/parameter/test ; - -# bring in rules for testing -import testing ; - -test-suite "parameter" - : [ run basics.cpp ] - [ run sfinae.cpp ] - [ run macros.cpp ] - [ run unnamed.cpp ] - [ run efficiency.cpp ] - [ compile unwrap_cv_reference.cpp ] - ; diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 deleted file mode 100644 index 1e6c037..0000000 --- a/test/Jamfile.v2 +++ /dev/null @@ -1,10 +0,0 @@ -# Boost Parameter Library test Jamfile - -test-suite "parameter" - : [ run basics.cpp ] - [ run sfinae.cpp ] - [ run macros.cpp ] - [ run unnamed.cpp ] - [ run efficiency.cpp ] - [ compile unwrap_cv_reference.cpp ] - ; diff --git a/test/basics.cpp b/test/basics.cpp deleted file mode 100755 index 81b7a00..0000000 --- a/test/basics.cpp +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright David Abrahams, Daniel Wallin 2003. Use, modification and -// distribution is subject to the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include - -#include "basics.hpp" - - -namespace test -{ - // A separate function for getting the "value" key, so we can deduce - // F and use lazy_binding on it. - template - typename boost::parameter::lazy_binding::type - extract_value(Params const& p, F const& f) - { - typename boost::parameter::lazy_binding< - Params, tag::value, F - >::type v = p[value || f ]; - return v; - } - - template - int f_impl(Params const& p) - { - typename boost::parameter::binding::type - n = p[name]; - - typename boost::parameter::binding< - Params, tag::value, double - >::type v = extract_value(p, boost::bind(&value_default)); - - typename boost::parameter::binding< - Params, tag::index, int - >::type i = -#if BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590042)) - p[test::index | 999]; -#else - p[index | 999]; -#endif - - p[tester](n,v,i); - - return 1; - } - - template - int f(Tester const& t, const Name& name_, - const Value& value_, const Index& index_) - { - return f_impl(f_parameters()(t, name_, value_, index_)); - } - - template - int f(Tester const& t, const Name& name_, const Value& value_) - { - return f_impl(f_parameters()(t, name_, value_)); - } - - template - int f(Tester const& t, const Name& name_) - { - return f_impl(f_parameters()(t, name_)); - } - - template - int f_list(Params const& params) - { - return f_impl(params); - } - -} - -int main() -{ - using test::f; - using test::f_list; - using test::name; - using test::value; - using test::index; - using test::tester; - - f( - test::values(S("foo"), S("bar"), S("baz")) - , S("foo"), S("bar"), S("baz") - ); - - int x = 56; - f( - test::values("foo", 666.222, 56) - , index = boost::ref(x), name = "foo" - ); - -#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) - // No comma operator available on Borland - f_list(( - tester = test::values("foo", 666.222, 56) - , index = boost::ref(x) - , name = "foo" - )); -#endif - - //f(index = 56, name = 55); // won't compile - return 0; -} - diff --git a/test/basics.hpp b/test/basics.hpp deleted file mode 100755 index e806356..0000000 --- a/test/basics.hpp +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright David Abrahams, Daniel Wallin 2005. Use, modification and -// distribution is subject to the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BASICS_050424_HPP -#define BASICS_050424_HPP - -#include -#include - -namespace test { - -BOOST_PARAMETER_KEYWORD(tag, name) -BOOST_PARAMETER_KEYWORD(tag, value) -BOOST_PARAMETER_KEYWORD(tag, index) -BOOST_PARAMETER_KEYWORD(tag, tester) - -using namespace boost::parameter; - -struct f_parameters // vc6 is happier with inheritance than with a typedef - : parameters< - tag::tester - , tag::name - , tag::value - , tag::index - > -{}; - -inline double value_default() -{ - return 666.222; -} - -template -inline bool equal(T const& x, T const& y) -{ - return x == y; -} - -inline bool equal(char const* s1, char const* s2) -{ - return !strcmp(s1,s2); -} - -#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) -inline bool equal(char* s1, char* s2) -{ - return !strcmp(s1,s2); -} -#endif - -template -struct values_t -{ - values_t(Name const& n, Value const& v, Index const& i) - : n(n), v(v), i(i) - {} - - template - void operator()(Name_ const& n_, Value_ const& v_, Index_ const& i_) const - { - - // Only VC and its emulators fail this; they seem to have - // problems with deducing the constness of string literal - // arrays. -#if defined(_MSC_VER) \ - && (BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, <= 700) \ - || BOOST_WORKAROUND(BOOST_MSVC, < 1310)) \ - || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) -# else - BOOST_STATIC_ASSERT((boost::is_same::value)); - BOOST_STATIC_ASSERT((boost::is_same::value)); - BOOST_STATIC_ASSERT((boost::is_same::value)); -#endif - assert(equal(n, n_)); - assert(equal(v, v_)); - assert(equal(i, i_)); - } - - Name const& n; - Value const& v; - Index const& i; -}; - -template -inline values_t -values(Name const& n, Value const& v, Index const& i) -{ - return values_t(n,v,i); -} - -} // namespace test - -// GCC2 has a problem with char (&)[] deduction, so we'll cast string -// literals there. -#undef S -#if BOOST_WORKAROUND(__GNUC__, == 2) || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) -# define S(s) (char const*)s -#else -# define S(s) s -#endif - -#endif // BASICS_050424_HPP - diff --git a/test/efficiency.cpp b/test/efficiency.cpp deleted file mode 100755 index 5eb0931..0000000 --- a/test/efficiency.cpp +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright David Abrahams, Matthias Troyer, Michael Gauckler -// 2005. Distributed under the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include - -namespace test -{ - // - // This test measures the abstraction overhead of using the named - // parameter interface. Some actual test results have been recorded - // in timings.txt in this source file's directory, or - // http://www.boost.org/libs/parameter/test/timings.txt. - // - // Caveats: - // - // 1. This test penalizes the named parameter library slightly, by - // passing two arguments through the named interface, while - // only passing one through the plain C++ interface. - // - // 2. This test does not measure the case where an ArgumentPack is - // so large that it doesn't fit in the L1 cache. - // - // 3. Although we've tried to make this test as general as - // possible, we are targeting it at a specific application. - // Where that affects design decisions, we've noted it below in - // ***...***. - // - // 4. The first time you run this program, the time may not be - // representative because of disk and memory cache effects, so - // always run it multiple times and ignore the first - // measurement. This approach will also allow you to estimate - // the statistical error of your test by observing the - // variation in the valid times. - // - // 5. Try to run this program on a machine that's otherwise idle, - // or other processes and even device hardware interrupts may - // interfere by causing caches to be flushed. - - // Accumulator function object with plain C++ interface - template - struct plain_weight_running_total - { - plain_weight_running_total() - : sum() - {} - - void operator()(T w) - { - this->sum += w; - } - - T sum; - }; - - BOOST_PARAMETER_KEYWORD(tag, weight) - BOOST_PARAMETER_KEYWORD(tag, value) - - // Accumulator function object with named parameter interface - template - struct named_param_weight_running_total - { - named_param_weight_running_total() - : sum() - {} - - template - void operator()(ArgumentPack const& variates) - { - this->sum += variates[weight]; - } - - T sum; - }; - - // This value is required to ensure that a smart compiler's dead - // code elimination doesn't optimize away anything we're testing. - // We'll use it to compute the return code of the executable to make - // sure it's needed. - double live_code; - - // Call objects of the given Accumulator type repeatedly with x as - // an argument. - template - void hammer(Arg const& x) - { - // Strategy: because the sum in an accumulator after each call - // depends on the previous value of the sum, the CPU's pipeline - // might be stalled while waiting for the previous addition to - // complete. Therefore, we allocate an array of accumulators, - // and update them in sequence, so that there's no dependency - // between adjacent addition operations. - // - // Additionally, if there were only one accumulator, the - // compiler or CPU might decide to update the value in a - // register rather that writing it back to memory. we want each - // operation to at least update the L1 cache. *** Note: This - // concern is specific to the particular application at which - // we're targeting the test. *** - - // This has to be at least as large as the number of - // simultaneous accumulations that can be executing in the - // compiler pipeline. A safe number here is larger than the - // machine's maximum pipeline depth. If you want to test the L2 - // or L3 cache, or main memory, you can increase the size of - // this array. 1024 is an upper limit on the pipeline depth of - // current vector machines. - const std::size_t number_of_accumulators = 1024; - - Accumulator a[number_of_accumulators]; - - for (long iteration = 0; iteration < 1000000; ++iteration) - { - for (Accumulator* ap = a; ap < a + number_of_accumulators; ++ap) - { - (*ap)(x); - } - } - - // Accumulate all the partial sums to avoid dead code - // elimination. - for (Accumulator* ap = a; ap < a + number_of_accumulators; ++ap) - { - live_code += ap->sum; - } - } - - // Measure the time required to hammer accumulators of the given - // type with the argument x. - template - double measure(T const& x) - { - // Hammer accumulators a couple of times to ensure the - // instruction cache is full of our test code, and that we don't - // measure the cost of a page fault for accessing the data page - // containing the memory where the accumulators will be - // allocated - hammer(x); - hammer(x); - - // Now start a timer - boost::timer time; - hammer(x); // This time, we'll measure - return time.elapsed(); - } -} - -int main() -{ - using namespace test; - - std::cout - << "plain time: " - << measure >(.1) - << std::endl; - - std::cout - << "named parameter time: " - << measure >( - (weight = .1, value = .2) - ) - << std::endl; - - // This is ultimately responsible for preventing all the test code - // from being optimized away. Change this to return 0 and you - // unplug the whole test's life support system. - return live_code < 0.; -} diff --git a/test/macros.cpp b/test/macros.cpp deleted file mode 100755 index 16cf695..0000000 --- a/test/macros.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright David Abrahams, Daniel Wallin 2003. Use, modification and -// distribution is subject to the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include -#include -#include - -#include "basics.hpp" - -namespace test -{ - - BOOST_PARAMETER_FUN(int, f, 2, 4, f_parameters) - { - p[tester]( - p[name] - , p[value || boost::bind(&value_default) ] -#if BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590042)) - , p[test::index | 999 ] -#else - , p[index | 999 ] -#endif - ); - - return 1; - } - -} // namespace test - -int main() -{ - using test::f; - using test::name; - using test::value; - using test::index; - using test::tester; - - f( - test::values(S("foo"), S("bar"), S("baz")) - , S("foo"), S("bar"), S("baz") - ); - - int x = 56; - f( - test::values("foo", 666.222, 56) - , index = boost::ref(x), name = "foo" - ); - - return 0; -} - diff --git a/test/sfinae.cpp b/test/sfinae.cpp deleted file mode 100755 index 309de8f..0000000 --- a/test/sfinae.cpp +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright David Abrahams, Daniel Wallin 2003. Use, modification and -// distribution is subject to the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt - -#include -#include -#include -#include -#include -#include - -#ifndef BOOST_NO_SFINAE -# include -# include -#endif - -namespace test -{ - BOOST_PARAMETER_KEYWORD(keywords,name) - BOOST_PARAMETER_KEYWORD(keywords,value) - - using namespace boost::parameter; - - struct f_parameters - : parameters< - optional< - keywords::name - , boost::is_convertible - > - , optional< - keywords::value - , boost::is_convertible - > - > - {}; - - template struct not_implemented; - - template - void f_impl(P const& p) - { - std::string s = p[name | "bar"]; - float v = p[value | 3.f]; - - assert(s == "foo"); - assert(v == 3.f); - } - - void f() - { - f_impl(f_parameters()()); - } - - using boost::parameter::aux::void_; - - template - void f( - A0 const& a0 - , BOOST_PARAMETER_MATCH(f_parameters, (A0), args)) - { - f_impl(args(a0)); - } - - template - void f( - A0 const& a0, A1 const& a1 - , BOOST_PARAMETER_MATCH(f_parameters,(A0)(A1), args)) - { - f_impl(args(a0, a1)); - } - -#ifndef BOOST_NO_SFINAE - // On compilers that actually support SFINAE, add another overload - // that is an equally good match and can only be in the overload set - // when the others are not. This tests that the SFINAE is actually - // working. On all other compilers we're just checking that - // everything about SFINAE-enabled code will work, except of course - // the SFINAE. - template - typename boost::enable_if, int>::type - f(A0 const& a0, A1 const& a1) - { - return 0; - } -#endif -} // namespace test - -int main() -{ - using test::name; - using test::value; - using test::f; - - f("foo"); - f("foo", 3.f); - f(value = 3.f, name = "foo"); - -#ifndef BOOST_NO_SFINAE - return f(3, 4); -#else - return 0; -#endif -} - diff --git a/test/timings.txt b/test/timings.txt deleted file mode 100755 index d15433b..0000000 --- a/test/timings.txt +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright David Abrahams 2005. Distributed under the Boost -# Software License, Version 1.0. (See accompanying -# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - ------------------ Test #1 ---------------- -Testers: - Matthias Troyer, Michael Gauckler, David Abrahams - -Date: - 2005-09-09 - -Compiler: - Cygwin g++-4.0.0 - -Command lines: - g++ -c -o efficiency.o -ftemplate-depth-100 -funroll-loops \ - -O3 -finline-functions -Wno-inline -DNDEBUG efficiency.cpp - - g++ -o efficiency.exe efficiency.o -Wl,--strip-all - - efficiency && efficiency && efficiency - -Machine: - Dell Inspiron 9300 - Intel(R) Pentium(R) M processor 2.00GHz - Running on 230 volts AC power - -Timings: - Run #1 results discarded per standard practice - - Run #2 - plain time: 0.75 - named parameter time: 0.734 - - Run #3 - plain time: 0.781 - named parameter time: 0.766 - ------------------------------------------ - diff --git a/test/unnamed.cpp b/test/unnamed.cpp deleted file mode 100755 index 35816c8..0000000 --- a/test/unnamed.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright David Abrahams, Daniel Wallin 2003. Use, modification and -// distribution is subject to the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace test -{ - using namespace boost::parameter; - namespace mpl = boost::mpl; - - BOOST_PARAMETER_KEYWORD(tag, name) - BOOST_PARAMETER_KEYWORD(tag, value) - - struct g_parameters - : parameters< - unnamed > - , unnamed > - > - {}; - - - // Keeping this out here avoids an ICE with vc-6.x - std::string const foo("foo"); - - template - int g_(Params const& p) - { - assert(p[name] == foo); - assert(p[value] == 3.14f); - return 1; - } - - template - int g(A0 const& a0, BOOST_PARAMETER_MATCH(g_parameters, (A0), args)) - { - return g_(args(a0)); - } - - template - int g(A0 const& a0, A1 const& a1, BOOST_PARAMETER_MATCH(g_parameters, (A0)(A1), args)) - { - return g_(args(a0, a1)); - } - -} - -#include -#include - -int main() -{ - using test::g; - using test::name; - using test::value; - - g("foo", 3.14f); - g(3.14f, "foo"); - - g(value = 3.14f, "foo"); - g(name = "foo", 3.14f); - g(3.14f, name = "foo"); - g(name = "foo", value = 3.14f); - - return 0; -} - diff --git a/test/unwrap_cv_reference.cpp b/test/unwrap_cv_reference.cpp deleted file mode 100755 index 5780e39..0000000 --- a/test/unwrap_cv_reference.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright David Abrahams 2005. Distributed under the Boost -// Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include - -namespace test -{ - using namespace boost::parameter::aux; - using namespace boost; - struct foo {}; - - BOOST_MPL_ASSERT((is_same::type,int>)); - BOOST_MPL_ASSERT((is_same::type,int const>)); - BOOST_MPL_ASSERT((is_same::type,int volatile>)); - BOOST_MPL_ASSERT((is_same::type,int const volatile>)); - - BOOST_MPL_ASSERT((is_same::type,foo>)); - BOOST_MPL_ASSERT((is_same::type,foo const>)); - BOOST_MPL_ASSERT((is_same::type,foo volatile>)); - BOOST_MPL_ASSERT((is_same::type,foo const volatile>)); - - BOOST_MPL_ASSERT((is_same >::type,foo>)); - BOOST_MPL_ASSERT((is_same const>::type,foo>)); - BOOST_MPL_ASSERT((is_same volatile>::type,foo>)); - BOOST_MPL_ASSERT((is_same const volatile>::type,foo>)); -}