diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b3eebf64..eb24d158 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -120,7 +120,7 @@ jobs: if: matrix.os == 'ubuntu-latest' uses: actions/upload-pages-artifact@v3 with: - path: doc/build/site + path: doc/html - name: Deploy to GitHub Pages (jll63) if: matrix.os == 'ubuntu-latest' && github.repository_owner == 'jll63' && github.ref_name == 'feature/doc' diff --git a/doc/Jamfile b/doc/Jamfile deleted file mode 100644 index da01a050..00000000 --- a/doc/Jamfile +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright 2018-2024 Peter Dimov -# -# 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) - -project doc/openmethod ; -using asciidoctor ; - -html index.html : openmethod.adoc : stylesheet=zajo-dark.css linkcss ; -install html_ : index.html skin.png zajo-dark.css zajo-light.css rouge-github.css : html ; - -# pdf openmethod.pdf : openmethod.adoc : book pdf-themesdir=. pdf-theme=openmethod ; -# install pdf_ : openmethod.pdf : html ; - -alias boostdoc ; -explicit boostdoc ; -alias boostrelease : html_ ; -explicit boostrelease ; diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 new file mode 100644 index 00000000..4ab15103 --- /dev/null +++ b/doc/Jamfile.v2 @@ -0,0 +1,57 @@ +import generate ; +import path ; +import property-set ; +import virtual-target ; + +path-constant HERE : . ; + +make html/index.html : build_antora.sh : @run-script ; +generate files-to-install : html/index.html : @delayed-glob ; +install install + : files-to-install + : html + html/openmethod + ; +explicit html/index.html files-to-install ; + +# this runs the antora script +actions run-script +{ + bash $(>) +} + +# this globs after its sources are created +rule delayed-glob ( project name : property-set : sources * ) +{ + for local src in $(sources) + { + # the next line causes the source to be generated immediately + # and not later (which it normally would) + UPDATE_NOW [ $(src).actualize ] ; + } + + # we need to construct the path to the globbed directory; + # this path would be /antora + local root = [ path.root html [ $(project).location ] ] ; + local files ; + + # actual globbing happens here + for local file in [ path.glob-tree $(root) : * ] + { + # we have to skip directories, because our match expression accepts anything + if [ CHECK_IF_FILE $(file) ] + { + # we construct a list of targets to copy + files += [ virtual-target.from-file $(file:D=) : $(file:D) : $(project) ] ; + } + } + + # we prepend empty usage requirements to the result + return [ property-set.empty ] $(files) ; +} + +############################################################################### +alias boostdoc ; +explicit boostdoc ; +alias boostrelease : install ; +explicit boostrelease ; \ No newline at end of file diff --git a/doc/html/index.html b/doc/html/index.html deleted file mode 100644 index bfdf5816..00000000 --- a/doc/html/index.html +++ /dev/null @@ -1,6256 +0,0 @@ - - - - - - - - -Boost.OpenMethod - - - - - -
-
-

Introduction

-
-
-

Open-methods are similar to virtual functions, but they are not required to be -members of a class. By being both free and virtual, they provide a solution to -the Expression Problem:

-
-
-
-
-

Given a set of types, and a set of operations on these types, is it possible -to add new operations on the existing types, and new types to the existing -operations, without modifying existing code?

-
-
-
-
-

Open-methods also address the banana-gorilla-shared problem:

-
-
-
-
-

The problem with object-oriented languages is they’ve got all this implicit -environment that they carry around with them. You wanted a banana but what you -got was a gorilla holding the banana and the entire shared. — Joe Armstrong, -creator of Erlang progamming language

-
-
-
-
-

As a bonus, open-methods can take more than one argument into account when -selecting the appropriate function to call - aka multiple dispatch. For that -reason, open-methods are often called multi-methods, but that term is -misleading, as it suggests that the feature is useful only when multiple -dispatch is needed. In reality, -it -has been observed that, in large systems written in languages that support -multi-methods, most methods use single-dispatch. The real benefit is in the -solution to the Expression Problem.

-
-
-

Open-methods were introduced by the Common Lisp Object System, and they are -native to many languages: Clojure, Julia, Dylan, TADS, Cecil, Diesel, Nice, etc. -Bjarne Stroustrup wanted open-methods in C++ almost from the beginning. In D&E -he writes:

-
-
-
-
-

I repeatedly considered a mechanism for a virtual function call based on more -than one object, often called multi-methods. I rejected multi-methods with -regret because I liked the idea, but couldn’t find an acceptable form under -which to accept it. […​] Multi-methods is one of the interesting what-ifs of -C++. Could I have designed and implemented them well enough at the time? Would -their applications have been important enough to warrant the effort? What other -work might have been left undone to provide the time to design and implement -multi-methods? Since about 1985, I have always felt some twinge of regret for -not providing multi-methods (Stroustrup, 1994, The Design and Evolution of -C++, 13.8).

-
-
-
-
-

Circa 2007, he and his PhD students Peter Pirkelbauer and Yuriy Solodkyy wrote a -series of papers and a prototype implementation based on the EDG compiler. -Unfortunately, open-methods never made it into the standard. Stroustrup bemoans, -in a more recent paper:

-
-
-
-
-

In retrospect, I don’t think that the object-oriented notation (e.g., x.f(y)) -should ever have been introduced. The traditional mathematical notation f(x,y) -is sufficient. As a side benefit, the mathematical notation would naturally have -given us multi-methods, thereby saving us from the visitor pattern workaround -(Stroustrup, 2020, Thriving in a Crowded and ChangingWorld: C++ 2006–2020).

-
-
-
-
-

This library implements the features described in the -N2216 paper, -with some extensions:

-
-
-
    -
  • -

    a mechanism for calling the next most specialized overrider

    -
  • -
  • -

    support for smart pointers

    -
  • -
  • -

    customization points for RTTI, error handling, tracing, smart pointers…​

    -
  • -
-
-
-

Multiple and virtual inheritance are supported, with the exception of repeated -inheritance.

-
-
-
-
-

Tutorials

-
-
-

Hello World

-
-

Consider the following program, intended to demonstrate the basics of virtual -functions:

-
-
-
-
#include <iostream>
-#include <memory>
-
-struct Animal {
-    Animal(std::string name) : name(name) {}
-    virtual ~Animal() = default;
-    virtual void poke(std::ostream&) = 0;
-    std::string name;
-};
-
-struct Cat : Animal {
-    using Animal::Animal;
-
-    void poke(std::ostream& os) override {
-        os << name << " hisses";
-    }
-};
-
-struct Dog : Animal {
-    using Animal::Animal;
-
-    void poke(std::ostream& os) override {
-        os << name << " barks";
-    }
-};
-
-struct Bulldog : Dog {
-    using Dog::Dog;
-
-    void poke(std::ostream& os) override {
-        Dog::poke(os);
-        os << " and bites back";
-    }
-};
-
-auto main() -> int {
-    std::unique_ptr<Animal> a(new Cat("Felix"));
-    std::unique_ptr<Animal> b(new Dog("Snoopy"));
-    std::unique_ptr<Animal> c(new Bulldog("Hector"));
-
-    a->poke(std::cout); // prints "Felix hisses"
-    std::cout << ".\n";
-
-    b->poke(std::cout); // prints "Snoopy barks"
-    std::cout << ".\n";
-
-    c->poke(std::cout); // prints "Hector barks and bites back"
-    std::cout << ".\n";
-
-    return 0;
-}
-
-
-
-

We are going to rewrite this using open-methods.

-
-
-

First we remove the poke virtual functions from the domain classes:

-
-
-
-
#include <string>
-
-struct Animal {
-    Animal(std::string name) : name(name) {}
-    std::string name;
-    virtual ~Animal() = default;
-};
-
-struct Cat : Animal {
-    using Animal::Animal;
-};
-
-struct Dog : Animal {
-    using Animal::Animal;
-};
-
-struct Bulldog : Dog {
-    using Dog::Dog;
-};
-
-
-
-

Note that the Animal classes do not depend on iostreams anymore. This is a major -advantage of open-methods over virtual functions: they make it possible to -better organize dependencies.

-
-
-

Let’s implement poke. First we need to include the library’s main header. It -defines a few macros, and injects a name - virtual_ptr - in the global -namespace.

-
-
-
-
#include <iostream>
-#include <boost/openmethod.hpp>
-
-using boost::openmethod::virtual_ptr;
-
-BOOST_OPENMETHOD(
-    poke,                                       // method name
-    (std::ostream&, virtual_ptr<Animal>),       // method signature
-    void);                                      // return type
-
-
-
-

This defines a free function called poke, which takes two arguments. The first -is the ostream. The second argument corresponds to the implicit this pointer -in a virtual function. It is now an explicit argument. Just like with virtual -functions, the exact function to execute is selected on the basis of the -argument’s dynamic type.

-
-
-

Unlike virtual functions, there is no such thing as a pure open-method that -would make a class abstract. It is not possible to determine if an overrider is -available from looking at just the current translation unit.

-
-
-

Let’s add overriders for Cat and Dog:

-
-
-
-
BOOST_OPENMETHOD_OVERRIDE(
-    poke,                                       // method name
-    (std::ostream & os, virtual_ptr<Cat> cat),  // overrider signature
-    void) {                                     // return type
-    os << cat->name << " hisses";               // overrider body
-}
-
-BOOST_OPENMETHOD_OVERRIDE(poke, (std::ostream & os, virtual_ptr<Dog> dog), void) {
-    os << dog->name << " barks";
-}
-
-
-
-

Bulldog::poke calls the poke it overrides in its Dog base. The equivalent -for open-methods is next, a function that is available only inside the body of -an overrider. It calls the next most specific overrider, i.e. what would have -been called if the overrider did not exist.

-
-
-
-
BOOST_OPENMETHOD_OVERRIDE(
-    poke, (std::ostream & os, virtual_ptr<Bulldog> dog), void) {
-    next(os, dog);                              // call base overrider
-    os << " and bites back";
-}
-
-
-
-

All classes involved in open-method calls need to be registered using the -BOOST_OPENMETHOD_CLASSES macro:

-
-
-
-
BOOST_OPENMETHOD_CLASSES(Animal, Cat, Dog, Bulldog);
-
-
-
-

Classes can be registered incrementally, as long as all the direct bases of a -class are listed with it in some call(s) to BOOST_OPENMETHOD_CLASSES. For -example, Bulldog can be added in a second call, as long as Dog is listed as -well:

-
-
-
-
// in animals.cpp
-BOOST_OPENMETHOD_CLASSES(Animal, Cat, Dog);
-
-// in bulldog.cpp
-BOOST_OPENMETHOD_CLASSES(Dog, Bulldog);
-
-
-
-

boost::openmethod::initialize(); must be called before any open-method call. -It builds the dispatch tables. Typically this is done in main:

-
-
-
-
#include <boost/openmethod/compiler.hpp>
-    // only needed in the file that calls boost::openmethod::initialize()
-
-auto main() -> int {
-    boost::openmethod::initialize();
-    // ...
-}
-
-
-
-

We call poke like any ordinary function. We can pass it the animals by -reference, because virtual_ptr has a conversion constructor for that:

-
-
-
-
    std::unique_ptr<Animal> felix(new Cat("Felix"));
-    std::unique_ptr<Animal> snoopy(new Dog("Snoopy"));
-    std::unique_ptr<Animal> hector(new Bulldog("Hector"));
-
-    poke(std::cout, *felix); // Felix hisses
-    std::cout << ".\n";
-
-    poke(std::cout, *snoopy); // Snoopy barks
-    std::cout << ".\n";
-
-    poke(std::cout, *hector); // Hector barks and bites
-    std::cout << ".\n";
-
-
-
-
-

Multiple Dispatch

-
-

A method can have more than one virtual_ptr parameter. For example:

-
-
-
-
BOOST_OPENMETHOD(
-    encounter,
-    (std::ostream&, virtual_ptr<Animal>, virtual_ptr<Animal>), void);
-
-// 'encounter' catch-all implementation.
-BOOST_OPENMETHOD_OVERRIDE(
-    encounter,
-    (std::ostream & os, virtual_ptr<Animal> a, virtual_ptr<Animal> b), void) {
-    os << a->name << " and " << b->name << " ignore each other";
-}
-
-// Add definitions for specific pairs of animals.
-BOOST_OPENMETHOD_OVERRIDE(
-    encounter,
-    (std::ostream & os, virtual_ptr<Dog> /*dog1*/, virtual_ptr<Dog> /*dog2*/), void) {
-    os << "Both wag tails";
-}
-
-BOOST_OPENMETHOD_OVERRIDE(
-    encounter, (std::ostream & os, virtual_ptr<Dog> dog, virtual_ptr<Cat> cat),
-    void) {
-    os << dog->name << " chases " << cat->name;
-}
-
-BOOST_OPENMETHOD_OVERRIDE(
-    encounter, (std::ostream & os, virtual_ptr<Cat> cat, virtual_ptr<Dog> dog),
-    void) {
-    os << cat->name << " runs away from " << dog->name;
-}
-
-
-
-
-
// cat and dog
-encounter(std::cout, *felix, *snoopy); // Felix runs away from Snoopy
-std::cout << ".\n";
-
-// dog and cat
-encounter(std::cout, *snoopy, *felix); // Snoopy chases Felix
-std::cout << ".\n";
-
-// dog and dog
-encounter(std::cout, *snoopy, *hector); // Both wag tails
-std::cout << ".\n";
-
-// cat and cat
-std::unique_ptr<Animal> tom(new Cat("Tom"));
-encounter(std::cout, *felix, *tom); // Felix and Tom ignore each other
-std::cout << ".\n";
-
-
-
-

The appropriate overrider is selected using a process similar to overload -resolution, with fallback options. If one overrider is more specialized than all -the others, call it. Otherwise, the return type is used as a tie-breaker, if -it is covariant with the return type of the base method. If there is still no -unique best overrider, one of the best overriders is chosen arbitrarily.

-
-
-
-

Headers and Namespaces

-
-

Most real-life programs will be organized in multiple files and multiple -namespaces. OpenMethod interacts with headers and namespaces naturally, if -using-directives are avoided. In that case, there are a few things to be aware -of.

-
-
-

Let’s break the Animals example into headers and namespaces. First we put -Animal in its own header and namespace:

-
-
-
-
// animal.hpp
-
-#ifndef ANIMAL_HPP
-#define ANIMAL_HPP
-
-#include <boost/openmethod.hpp>
-#include <string>
-
-namespace animals {
-
-struct Animal {
-    Animal(std::string name) : name(name) {
-    }
-    std::string name;
-    virtual ~Animal() = default;
-};
-
-BOOST_OPENMETHOD(
-    poke, (std::ostream&, boost::openmethod::virtual_ptr<Animal>), void);
-
-} // namespace animals
-
-#endif // ANIMAL_HPP
-
-
-
-

BOOST_OPENMETHOD can be placed in a header file. It adds several constructs to -the current namespace:

-
-
-
    -
  • -

    It declares (but does not define) a struct named after the method.

    -
  • -
  • -

    It declares (but does not define) a guide function. It is also named after -the method, and it has the same signature (with the virtual_ decorators -stripped). It is used to match methods and overriders. It is never defined and -it is "called" only in a non-evaluated context.

    -
  • -
  • -

    It defines an inline function with the same name and signature as the -method (with the virtual_ decorators stripped).

    -
  • -
-
-
-

Next, let’s implement the Cat class, and a derived class, Cheetah, in the -felines namespace:

-
-
-
-
// felines.hpp
-
-#ifndef FELINES_HPP
-#define FELINES_HPP
-
-#include "animal.hpp"
-
-namespace felines {
-
-struct Cat : animals::Animal {
-    using Animal::Animal;
-};
-
-struct Cheetah : Cat {
-    using Cat::Cat;
-};
-
-} // namespace felines
-
-#endif // FELINES_HPP
-
-
-
-
-
// cat.cpp
-
-#include <iostream>
-#include <boost/openmethod.hpp>
-
-#include "cat.hpp"
-
-using boost::openmethod::virtual_ptr;
-
-namespace felines {
-
-BOOST_OPENMETHOD_CLASSES(animals::Animal, Cat, Cheetah);
-
-BOOST_OPENMETHOD_OVERRIDE(
-    poke, (std::ostream & os, virtual_ptr<Cat> cat), void) {
-    os << cat->name << " hisses";
-}
-
-BOOST_OPENMETHOD_OVERRIDE(
-    poke, (std::ostream & os, virtual_ptr<Cheetah> cat), void) {
-    BOOST_OPENMETHOD_OVERRIDER(
-        poke, (std::ostream & os, virtual_ptr<Cat> dog), void)::fn(os, cat);
-    os << " and runs away";
-}
-
-} // namespace felines
-
-
-
-

BOOST_OPENMETHOD_CLASSES should be placed in an implementation file. It can -also go in a header file, but this wastes space, as the same registrar will be -created in every translation unit that includes the header. It doesn’t matter -which namespace the macro is called in. It can take be used with any class name -in scope, or with qualified names.

-
-
-

BOOST_OPENMETHOD_OVERRIDE uses the guide function declared by -BOOST_OPENMETHOD to locate a method that can be called with the same arguments -as the overrider itself. It "calls" the guide function in a non-evaluated -context, passing it a std::ostream& and a virtual_ptr<Cat>. The return type -of the guide function is the method to add the overrider to. Exactly one guide -function must match. The normal rules of overload resolution apply. In that -case, the guide function is found via argument dependant lookup (ADL).

-
-
-

The macro adds several constructs to the current namespace:

-
-
-
    -
  • -

    It declares (but does not define) a struct template with one type parameter, -named after the method. The template acts like a container for overriders.

    -
  • -
  • -

    It specializes the template for the signature of the overrider. Inside the -struct, it defines the next and has_next members, and a static function -called fn. The block following the macro is the body of the fn function.

    -
  • -
-
-
-

It follows that BOOST_OPENMETHOD_OVERRIDE should be placed in an -implementation file. BOOST_OPENMETHOD_INLINE_OVERRIDE works like -BOOST_OPENMETHOD_OVERRIDE, but it defines the fn function as inline, so it -can be used in a header file.

-
-
-

The overrider for Cats can be accessed in the same translation unit, after it -has been defined, using the BOOST_OPENMETHOD_OVERRIDER macro. It expands to -the specialization of the overrider container for the overrider’s signature. We -call the static fn function to call the overrider.

-
-
- - - - - -
-
Note
-
-The Cheetah overrider calls the specific overrider for Cat, for -illustration purpose. It is usually better to call next instead. -
-
-
-

Let’s implement the Dog class, in the canines namespace. This time we want -the overrider to be accessible in other translation units. We can declare an -overrider with BOOST_OPENMETHOD_DECLARE_OVERRIDER, without actually defining -the static function fn just yet.

-
-
-
-
#ifndef CANINES_HPP
-#define CANINES_HPP
-
-#include <iosfwd>
-#include <boost/openmethod.hpp>
-
-#include "animal.hpp"
-
-namespace canines {
-
-struct Dog : animals::Animal {
-    using Animal::Animal;
-};
-
-BOOST_OPENMETHOD_DECLARE_OVERRIDER(
-    poke, (std::ostream & os, boost::openmethod::virtual_ptr<Dog> dog), void);
-
-} // namespace canines
-
-#endif // CANINES_HPP
-
-
-
-

Unlike function declarations, which can occur multiple times in a TU, an -overrider declaration cannot. For example, this is illegal:

-
-
-
-
BOOST_OPENMETHOD_DECLARE_OVERRIDER(
-    poke, (std::ostream&, virtual_ptr<Dog>), void);
-
-BOOST_OPENMETHOD_DECLARE_OVERRIDER(
-    poke, (std::ostream&, virtual_ptr<Dog>), void);
-
-
-
-

Now we use BOOST_OPENMETHOD_DEFINE_OVERRIDER to define the overrider:

-
-
-
-
#include <iostream>
-#include <boost/openmethod.hpp>
-
-#include "dog.hpp"
-
-namespace canines {
-
-BOOST_OPENMETHOD_CLASSES(animals::Animal, Dog);
-
-BOOST_OPENMETHOD_DEFINE_OVERRIDER(
-    poke, (std::ostream & os, boost::openmethod::virtual_ptr<Dog> dog), void) {
-    os << dog->name << " barks";
-}
-
-} // namespace canines
-
-
-
-

Let’s look at the main program now. It derived Bulldog from Dog and provides -an overrider for the new class:

-
-
-
-
#include <iostream>
-#include <boost/openmethod.hpp>
-#include <boost/openmethod/compiler.hpp>
-
-#include "animal.hpp"
-#include "cat.hpp"
-#include "dog.hpp"
-
-using boost::openmethod::virtual_ptr;
-
-struct Bulldog : canines::Dog {
-    using Dog::Dog;
-};
-
-BOOST_OPENMETHOD_CLASSES(canines::Dog, Bulldog);
-
-BOOST_OPENMETHOD_OVERRIDE(
-    poke, (std::ostream & os, virtual_ptr<Bulldog> dog), void) {
-    canines::BOOST_OPENMETHOD_OVERRIDER(
-        poke, (std::ostream & os, virtual_ptr<canines::Dog> dog),
-        void)::fn(os, dog);
-    os << " and bites back";
-}
-
-auto main() -> int {
-    boost::openmethod::initialize();
-
-    std::unique_ptr<animals::Animal> felix(new felines::Cat("Felix"));
-    std::unique_ptr<animals::Animal> azaad(new felines::Cheetah("Azaad"));
-    std::unique_ptr<animals::Animal> snoopy(new canines::Dog("Snoopy"));
-    std::unique_ptr<animals::Animal> hector(new Bulldog("Hector"));
-
-    poke(std::cout, *felix); // Felix hisses
-    std::cout << ".\n";
-
-    poke(std::cout, *azaad); // Azaad hisses and runs away
-    std::cout << ".\n";
-
-    poke(std::cout, *snoopy); // Snoopy barks
-    std::cout << ".\n";
-
-    poke(std::cout, *hector); // Hector barks and bites
-    std::cout << ".\n";
-
-    return 0;
-}
-
-
-
-

Again ADL plays a role: it helps the overrider (and main) to locate the poke -method.

-
-
-

This example is the "happy scenario", where namespaces are used conservatively.

-
-
-

The OVERRIDE macros don’t interact well with using directives. For example -this code:

-
-
-
-
using namespace animals;
-using namespace canines;
-using namespace felines;
-
-struct Bulldog : Dog {
-    using Dog::Dog;
-};
-
-BOOST_OPENMETHOD_CLASSES(Dog, Bulldog);
-
-BOOST_OPENMETHOD_OVERRIDE(
-    poke, (std::ostream & os, virtual_ptr<Bulldog> dog), void) {
-    next(os, dog);
-    os << " and bites back";
-}
-
-
-
-

…​will fail to compile, with an error like "reference to -'poke_boost_openmethod_overriders' is ambiguous". That is because the overrider -containers exist in both the canines and felines namespaces, with the same name.

-
-
-

Finally, the names passed as first arguments to the BOOST_OPENMETHOD and -BOOST_OPENMETHOD_OVERRIDE macros must be identifiers. Qualified names are not -allowed. Consider:

-
-
-
-
using animals::Animal;
-
-namespace app_specific_behavior {
-
-BOOST_OPENMETHOD(
-    meet, (std::ostream&, virtual_ptr<Animal>, virtual_ptr<Animal>), void);
-
-} // namespace app_specific_behavior
-
-BOOST_OPENMETHOD_OVERRIDE(
-    meet, (std::ostream& os, virtual_ptr<Animal>, virtual_ptr<Animal>), void) {
-    os << "ignore";
-}
-
-
-
-

Here, the guide function cannot be found, even via ADL. We get an error like -"use of undeclared identifier 'meet_boost_openmethod_guide'". How do we solve -this? We might be tempted to use a qualified name: -app_specific_behavior::meet:

-
-
-
-
BOOST_OPENMETHOD_OVERRIDE(
-    app_specific_behavior::meet,
-    (std::ostream& os, virtual_ptr<Animal>, virtual_ptr<Animal>), void) {
-    os << "ignore";
-}
-
-
-
-

But BOOST_OPENMETHOD_OVERRIDE also uses the name to derive the overrider -container’s name, using preprocessor token pasting, resulting in an invalid -declaration error.

-
-
-

We need to do is to make BOOST_OPENMETHOD_OVERRIDE "see" the guide function. -Its name is returned by macro BOOST_OPENMETHOD_GUIDE(NAME). We can use a -using-declaration to bring the guide function into the current scope:

-
-
-
-
using app_specific_behavior::BOOST_OPENMETHOD_GUIDE(meet);
-
-BOOST_OPENMETHOD_OVERRIDE(
-    meet, (std::ostream& os, virtual_ptr<Animal>, virtual_ptr<Animal>), void) {
-    os << "ignore";
-}
-
-
-
-
-

Friendship

-
-

We can use overrider containers to grant friendship to a specific overrider, or -to all the overriders of a method. The name of the container template is -returned by BOOST_OPENMETHOD_OVERRIDERS. The template argument for a -specialization is the signature of the overrider. For example, the overrider of -poke for Cat is:

-
-
-
-
BOOST_OPENMETHOD_OVERRIDERS(poke)<
-    void(std::ostream& os, virtual_ptr<Cat> cat)>::fn;
-
-
-
-

We can thus grant friendship to all the overriders of poke:

-
-
-
-
class Cat;
-class Dog;
-
-class Animal {
-    // ...
-  private:
-    std::string name;
-
-    template<typename> friend struct BOOST_OPENMETHOD_OVERRIDERS(poke);
-};
-
-
-
-

Be aware, though, that the overriders of any method called poke - with any -signature - are granted friendship.

-
-
-

We can also befriend individual overriders:

-
-
-
-
class Cat;
-class Dog;
-
-template<typename> struct BOOST_OPENMETHOD_OVERRIDERS(poke);
-
-class Animal {
-    // ...
-  private:
-    std::string name;
-
-    friend struct BOOST_OPENMETHOD_OVERRIDERS(poke)<void(std::ostream&, virtual_ptr<Cat>)>;
-    friend struct BOOST_OPENMETHOD_OVERRIDERS(poke)<void(std::ostream&, virtual_ptr<Dog>)>;
-};
-
-
-
-
-

Performance

-
-

Open-methods are almost as fast as ordinary virtual member functions when -compiled with optimization.

-
-
-

clang compiles the following code:

-
-
-
-
void call_poke_via_ref(std::ostream& os, Animal& a) {
-    poke(os, a);
-}
-
-
-
-

…​to this on the x64 architecture (variable names have been shortened for -readability):

-
-
-
-
mov	    rax, qword ptr [rsi]
-mov	    rdx, qword ptr [rip + mult]
-imul	rdx, qword ptr [rax - 8]
-movzx	ecx, byte ptr [rip + shift]
-shr	    rdx, cl
-mov	    rax, qword ptr [rip + vptrs]
-mov	    rax, qword ptr [rax + 8*rdx]
-mov	    rcx, qword ptr [rip + poke::slots_strides]
-mov	    rax, qword ptr [rax + 8*rcx]
-jmp	    rax
-
-
-
-

llvm-mca estimates a throughput of 4 cycles per dispatch. Comparatively, calling -a native virtual functions takes one cycle. However, the difference is amortized -by the time spent passing the arguments and returning from the function; plus, -of course, executing the body of the function.

-
-
-

Micro benchmarks suggest that dispatching an open-methods with a single virtual -argument is between 30% and 50% slower than calling the equivalent virtual -function, with an empty body and no other arguments.

-
-
-

However, call_poke does two things: it constructs a virtual_ptr<Animal> from -an Animal&; and then it calls the method. The construction of the -virtual_ptr is the costly part, as it involves a hash table lookup. Once that -price has been paid, the virtual_ptr can be used multiple times. It is passed -to the overrider, which can make further method calls through it. It can be -stored in variables in place of plain pointers.

-
-
-

Let’s look at another example: an AST for an arithmetic calculator:

-
-
-
-
#include <iostream>
-
-#include <boost/openmethod.hpp>
-#include <boost/openmethod/compiler.hpp>
-
-using boost::openmethod::virtual_ptr;
-
-struct Node {
-    virtual ~Node() {}
-};
-
-struct Literal : Node {
-    explicit Literal(int value) : value(value) {}
-
-    int value;
-};
-
-struct Plus : Node {
-    Plus(virtual_ptr<Node> left, virtual_ptr<Node> right)
-        : left(left), right(right) {}
-
-    virtual_ptr<Node> left, right;
-};
-
-struct Negate : Node {
-    explicit Negate(virtual_ptr<Node> node) : child(node) {}
-
-    virtual_ptr<Node> child;
-};
-
-BOOST_OPENMETHOD(value, (virtual_ptr<Node>), int);
-
-BOOST_OPENMETHOD_OVERRIDE(value, (virtual_ptr<Literal> node), int) {
-    return node->value;
-}
-
-BOOST_OPENMETHOD_OVERRIDE(value, (virtual_ptr<Plus> node), int) {
-    return value(node->left) + value(node->right);
-}
-
-BOOST_OPENMETHOD_OVERRIDE(value, (virtual_ptr<Negate> node), int) {
-    return -value(node->child);
-}
-
-BOOST_OPENMETHOD_CLASSES(Node, Literal, Plus, Negate);
-
-auto main() -> int {
-    boost::openmethod::initialize();
-
-    Literal one(1), two(2);
-    Plus sum(one, two);
-    Negate neg(sum);
-
-    std::cout << value(neg) << "\n"; // -3
-
-    return 0;
-}
-
-
-
-

The Negate overrider compiles to:

-
-
-
-
mov	rdi,    qword ptr [rsi + 8]
-mov	rsi,    qword ptr [rsi + 16]
-
-mov	rax,    qword ptr [rip + value::slots_strides]
-call	    qword ptr [rdi + 8*rax]
-
-neg	        eax
-pop	        rcx
-
-
-
-

The first two instructions read the virtual_ptr from this - placing its -content in registers rdi and rsi.

-
-
-

The next two instructions are the method call proper. According to llvm-mca, -they take one cycle - the same as a native virtual function call.

-
-
-

When we create the Plus and Negate nodes, we call the conversion -constructors of virtual_ptr<Node>, which occur the cost of hash table lookups. -However, in this example, we know the exact types of the objects. In that case, -we can use final_virtual_ptr to construct the virtual_ptr using a single -instruction. For example:

-
-
-
-
Literal one(1);
-Negate neg(boost::openmethod::final_virtual_ptr(one));
-
-
-
-

…​compiles to:

-
-
-
-
;; construct Literal
-lea	rax, [rip + vtable for Literal+16]
-mov	qword ptr [rsp], rax
-mov	dword ptr [rsp+8], 1
-
-;; construct Negate
-mov	rax, qword ptr [rip+static_vptr<Literal>] ; address of openmethod v-table
-lea	rcx, [rip+vtable for Negate+16]           ; address of native v-table
-mov	qword ptr [rsp+16], rcx                   ; set native v-table
-mov	qword ptr [rsp+24], rax                   ; set openmethod v-table
-mov	rax, rsp                                  ; address of 'one'
-mov	qword ptr [rsp+32], rax                   ; set vptr object pointer to 'one'
-
-
-
-

final_virtual_ptr does not require its argument to have a polymorphic type.

-
-
-
-

Smart Pointers

-
-

virtual_ptr can also be used in combination with smart pointers. -virtual_ptr<std::shared_ptr<Class>> (aliased to shared_virtual_ptr<Class>) -and virtual_ptr<std::unique_ptr<Class>> (aliased to -unique_virtual_ptr<Class>) deliver the convenience of automatic memory -management with the speed of virtual_ptr. Convenience functions -make_shared_virtual and make_unique_virtual create an object and return a -smart virtual_ptr to it. Since the exact type of the object is known, the vptr -is read from a static variable, without incuring the cost of a hash table -lookup.

-
-
-

Here is a variaton of the AST example that uses dynamic allocation and unique -pointers:

-
-
-
-
#include <iostream>
-#include <memory>
-
-#include <boost/openmethod.hpp>
-#include <boost/openmethod/interop/std_unique_ptr.hpp>
-#include <boost/openmethod/compiler.hpp>
-
-using namespace boost::openmethod::aliases;
-
-struct Node {
-    virtual ~Node() {}
-};
-
-struct Literal : Node {
-    Literal(int value) : value(value) {}
-
-    int value;
-};
-
-struct Plus : Node {
-    Plus(unique_virtual_ptr<Node> left, unique_virtual_ptr<Node> right)
-        : left(std::move(left)), right(std::move(right)) {}
-
-    unique_virtual_ptr<Node> left, right;
-};
-
-struct Negate : Node {
-    Negate(unique_virtual_ptr<Node> node) : child(std::move(node)) {}
-
-    unique_virtual_ptr<Node> child;
-};
-
-BOOST_OPENMETHOD(value, (virtual_ptr<Node>), int);
-
-BOOST_OPENMETHOD_OVERRIDE(value, (virtual_ptr<Literal> node), int) {
-    return node->value;
-}
-
-BOOST_OPENMETHOD_OVERRIDE(value, (virtual_ptr<Plus> node), int) {
-    return value(node->left) + value(node->right);
-}
-
-BOOST_OPENMETHOD_OVERRIDE(value, (virtual_ptr<Negate> node), int) {
-    return -value(node->child);
-}
-
-BOOST_OPENMETHOD_CLASSES(Node, Literal, Plus, Negate);
-
-auto main() -> int {
-    boost::openmethod::initialize();
-
-    auto expr = make_unique_virtual<Negate>(
-        make_unique_virtual<Plus>(
-            make_unique_virtual<Literal>(1),
-            make_unique_virtual<Literal>(2)));
-
-    std::cout << value(expr) << "\n"; // -3
-
-    return 0;
-}
-
-
-
-
-

Alternatives to virtual_ptr

-
-

Virtual arguments can be passed as plain references. In a method declaration, -parameters with a type decorated with virtual_ are considered in overrider -selection (along with virtual_ptr parameters).

-
-
-

For example, the poke open-method in the Animals example can be rewritten as:

-
-
-
-
struct Animal {
-    virtual ~Animal() = default;
-};
-
-struct Cat : Animal {};
-
-using boost::openmethod::virtual_;
-
-BOOST_OPENMETHOD(poke, (std::ostream&, virtual_<Animal&>), void);
-
-BOOST_OPENMETHOD_OVERRIDE(poke, (std::ostream & os, Cat& /*cat*/), void) {
-    os << "hiss";
-}
-
-BOOST_OPENMETHOD_CLASSES(Animal, Cat);
-
-int main() {
-    boost::openmethod::initialize();
-
-    Cat cat;
-    poke(std::cout, cat); // hiss
-}
-
-
-
-

Note that virtual_ is not used in the overrider. It is also removed from the -method’s signature.

-
-
-

By itself, virtual_ does not provide any benefits. Passing the virtual -argument by reference almost compiles to the same code as creating a -virtual_ptr, using it for one call, then throwing it way. The only difference -is that the virtual argument is passed as one pointer instead of two.

-
-
-

However, we can now customize how the vptr is obtained. When the method sees a -virtual_ parameter, it looks for a boost_openmethod_vptr function that takes -the parameter (by const reference), and returns a vptr_type. If one is found, -it is called to obtain the vptr. The vptr for a specific registered class can be -obtained via a variable template static_vptr, nested in class default_registry -(more on policies below).

-
-
-

In the following example, we embed a vptr in the object, just like the vptr for -native virtual functions:

-
-
-
-
class Animal {
-  protected:
-    boost::openmethod::vptr_type vptr;
-    friend auto boost_openmethod_vptr(const Animal& a, void*) {
-        return a.vptr;
-    }
-
-  public:
-    Animal() {
-        vptr = boost::openmethod::default_registry::static_vptr<Animal>;
-    }
-};
-
-class Cat : public Animal {
-  public:
-    Cat() {
-        vptr = boost::openmethod::default_registry::static_vptr<Cat>;
-    }
-};
-
-BOOST_OPENMETHOD(poke, (std::ostream&, virtual_<Animal&>), void);
-
-BOOST_OPENMETHOD_OVERRIDE(poke, (std::ostream & os, Cat& /*cat*/), void) {
-    os << "hiss\n";
-}
-
-BOOST_OPENMETHOD_CLASSES(Animal, Cat);
-
-int main() {
-    boost::openmethod::initialize();
-
-    Cat cat;
-    poke(std::cout, cat); // hiss
-}
-
-
-
- - - - - -
-
Note
-
-With this approach, classes need not be polymorphic. A virtual -destructor might be needed for correct destruction of objects, but it is not -required by the library. -
-
-
-

The inplace_vptr CRTP class automates the creation and management of embedded -vptrs.

-
-
-
-
#include <boost/openmethod/inplace_vptr.hpp>
-
-class Animal : public boost::openmethod::inplace_vptr<Animal> {
-};
-
-class Cat : public Animal, public boost::openmethod::inplace_vptr<Cat, Animal> {
-};
-
-BOOST_OPENMETHOD(poke, (std::ostream&, virtual_<Animal&>), void);
-
-BOOST_OPENMETHOD_OVERRIDE(poke, (std::ostream & os, Cat& /*cat*/), void) {
-    os << "hiss\n";
-}
-
-int main() {
-    boost::openmethod::initialize();
-
-    Cat cat;
-    poke(std::cout, cat); // hiss
-}
-
-
-
-

If inplace_vptr is passed only the class being defined, it adds a vptr to it, and -defines a boost_openmethod_vptr friend function. If more classes are passed, -they must be the direct bases of the class potentially involved in open-method -calls. Its constructor and destructor set the vptr to point to the v-table for -the class. inplace_vptr also takes care of registering the classes, so this time -the call to BOOST_OPENMETHOD_CLASSES is not needed.

-
-
-
-

Core API

-
-

OpenMethod provides a macro-free interface: the core API. This is useful in -certain situations, for example when combining open-methods and templates.

-
-
-

Let’s rewrite the Animals example using the core API. An open-method is -implemented as an instance of the method template. Its parameters are a -function signature and a return type:

-
-
-
-
#include <boost/openmethod/core.hpp>
-
-using namespace boost::openmethod;
-
-class poke_openmethod;
-
-using poke = method<
-    poke_openmethod(std::ostream&, virtual_<Animal&>), void>;
-
-
-
-

The poke_openmethod class acts as the method’s identifier: it separates it -from other methods with the same signature. The exact name does not really -matter, and the class needs not be defined, only declared. Inventing a class -name can get tedious, so OpenMethod provides a macro for that:

-
-
-
-
#include <boost/openmethod/macros.hpp>
-
-class BOOST_OPENMETHOD_ID(poke);
-
-using poke = method<
-    BOOST_OPENMETHOD_ID(poke),
-    auto(std::ostream&, virtual_ptr<Animal>)->void>;
-
-
-
- - - - - -
-
Note
-
-BOOST_OPENMETHOD and associated macros use BOOST_OPENMETHOD_ID in -their implementation. This makes it possible to mix the "macro" and "core" -styles. -
-
-
-

We call the method via the nested function object fn:

-
-
-
-
poke::fn(std::cout, animal);
-
-
-
-

Overriders are ordinary functions, added to a method using the nested template -override:

-
-
-
-
auto poke_cat(std::ostream& os, virtual_ptr<Cat> /*cat*/) {
-    os << "hiss";
-}
-
-static poke::override<poke_cat> override_poke_cat;
-
-
-
- - - - - -
-
Note
-
-override can register multiple overriders. -
-
-
-

In C++26, we will be able to use _ instead of inventing a one-time-use -identifier. In the meantime, OpenMethod provides a small convenience macro:

-
-
-
-
#include <boost/openmethod/macros.hpp>
-
-auto poke_dog(std::ostream& os, virtual_ptr<Dog> /*dog*/) {
-    os << "bark";
-}
-
-BOOST_OPENMETHOD_REGISTER(poke::override<poke_dog>);
-
-
-
-

next is available from the method’s nested next template:

-
-
-
-
auto poke_bulldog(std::ostream& os, virtual_ptr<Bulldog> dog) -> void {
-    poke::next<poke_bulldog>(os, dog);
-    os << " and bite";
-}
-
-BOOST_OPENMETHOD_REGISTER(poke::override<poke_bulldog>);
-
-
-
- - - - - -
-
Note
-
-Since the function uses itself as a template argument in its body, its -return type cannot be deduced. It must be specified explicitly, either by using -the old function declaration style or a trailing return type. -
-
-
-

Why not call poke_dog directly? We could; however, keep in mind that, in a -real program, a translation unit is not necessarily aware of the overriders -added elsewhere - especially in presence of dynamic loading.

-
-
-

We register the classes with use_classes:

-
-
-
-
BOOST_OPENMETHOD_REGISTER(use_classes<Animal, Cat, Dog, Bulldog>);
-
-
-
-

Finally, we call the method via the static member of the method class fn:

-
-
-
-
auto main() -> int {
-    boost::openmethod::initialize();
-
-    std::unique_ptr<Animal> a(new Cat);
-    std::unique_ptr<Animal> b(new Dog);
-    std::unique_ptr<Animal> c(new Bulldog);
-
-    poke::fn(std::cout, *a); // prints "hiss"
-    std::cout << "\n";
-
-    poke::fn(std::cout, *b); // prints "bark"
-    std::cout << "\n";
-
-    poke::fn(std::cout, *c); // prints "bark and bite"
-    std::cout << "\n";
-
-    return 0;
-
-
-
-
-

Policies and Facets

-
-

Methods and classes are scoped in a policy. A method can only reference classes -registered in the same policy. If a class is used as a virtual parameter in -methods using different policies, it must be registered with each of them.

-
-
-

Class templates use_classes, method, virtual_ptr, and macros -BOOST_OPENMETHOD and BOOST_OPENMETHOD_CLASSES, accept an additional -argument, a policy class, which defaults to policies::debug in debug builds, -and policies::release in release builds.

-
-
-

A policy has a collection of policys. Each policy belongs to a policy category. A -policy may contain at most one policy of a given category. Facets control how -type information is obtained, how vptrs are fetched, how errors are handled and -printed, etc. Some are used in initialize and method dispatch; some are used -by other policys in the same policy as part of their implementation. See the -reference for the list of policys. Policies and policys are placed in the -boost::openmethod::policies namespace. Two stock policies are provided by the -library: release and debug.

-
-
-

The release policy contains the following policys:

-
- ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
policy categorypolicyrole

rtti

std_rtti

provides type information for classes and objects

extern_vptr

vptr_vector

stores vptrs in an indexed collection

type_hash

fast_perfect_hash

hash type id to an index in a vector

error_handler

default_error_handler

handles errors

-
-

The debug policy contains the same policys as release, plus a few more:

-
- ----- - - - - - - - - - - - - - - - - - - - - - - - - -
policy categorypolicyrole

runtime_checks

(itself)

enables runtime checks

output

basic_error_output

prints error descriptions to stderr

trace

basic_trace_output

enables initialize to print information about dispatch table construction to stderr

-
-

Policies, and some policys, have static variables. When it is the case, they are -implemented as CRTP classes.

-
-
-

Policies can be created from scratch, using the basic_policy template, or -constructed from existing policies by adding and removing policys. For example, -policies::debug is a tweak of policies::release:

-
-
-
-
namespace boost::openmethod::policies {
-
-struct debug : release::fork<debug>::with<
-                   runtime_checks, basic_error_output<debug>,
-                   basic_trace_output<debug>> {};
-
-}
-
-
-
-

boost::openmethod::default_registry is an alias to release or debug, -depending on the value of preprocessor symbols NDEBUG. The default policy can -be overriden by defining the macroprocessor symbol -BOOST_OPENMETHOD_DEFAULT_REGISTRY before including -<boost/openmethod/core.hpp>. The value of the symbol is used as a default -template parameter for use_classes, method, virtual_ptr, and others. Once -the core header has been included, changing BOOST_OPENMETHOD_DEFAULT_REGISTRY -has no effect.

-
-
-
-

Error Handling

-
-

When an error is encountered, the program is terminated by a call to abort. If -the policy contains an error_handler policy, it provides an error member -function (or overloaded functions) to be called with an object identifying the -error. The release and debug policies implement the error policy with -default_error_handler, which wraps the error object in a variant, and calls a -handler via a std::function. By default, it prints a description of the error -to stderr in the debug policy, and does nothing in the release policy. The -handler can be set with set_error_handler:

-
-
-
-
#include <iostream>
-#include <variant>
-
-#include <boost/openmethod.hpp>
-#include <boost/openmethod/compiler.hpp>
-
-using boost::openmethod::virtual_ptr;
-
-struct Animal {
-    virtual ~Animal() = default;
-};
-
-struct Cat : Animal {};
-struct Dog : Animal {};
-
-BOOST_OPENMETHOD_CLASSES(Animal, Cat, Dog);
-
-BOOST_OPENMETHOD(trick, (std::ostream&, virtual_ptr<Animal>), void);
-
-BOOST_OPENMETHOD_OVERRIDE(
-    trick, (std::ostream & os, virtual_ptr<Dog> /*dog*/), void) {
-    os << "spin\n";
-}
-
-auto main() -> int {
-    namespace bom = boost::openmethod;
-    bom::initialize();
-
-    bom::default_registry::error_handler::set([](const auto& error) {
-        if (std::holds_alternative<bom::not_implemented_error>(error)) {
-            throw std::runtime_error("not implemented");
-        }
-    });
-
-    Cat felix;
-    Dog hector, snoopy;
-    std::vector<Animal*> animals = {&hector, &felix, &snoopy};
-
-    for (auto animal : animals) {
-        try {
-            trick(std::cout, *animal);
-        } catch (std::runtime_error& error) {
-            std::cerr << error.what() << "\n";
-        }
-    }
-
-    return 0;
-}
-
-
-
-

Output:

-
-
-
-
spin
-not implemented
-spin
-
-
-
-

We can also replace the error_handler policy with our own. For example:

-
-
-
-
#include <iostream>
-
-#include <boost/openmethod/default_registry.hpp>
-
-struct Animal {
-    virtual ~Animal() = default;
-};
-
-struct Cat : Animal {};
-struct Dog : Animal {};
-
-namespace bom = boost::openmethod;
-
-struct throw_if_not_implemented : bom::policies::error_handler {
-    template<class Registry>
-    struct fn {
-        static auto error(const bom::openmethod_error&) -> void {
-        }
-
-        static auto error(const bom::not_implemented_error& err) -> void {
-            throw err;
-        }
-    };
-};
-
-struct custom_registry : bom::default_registry::with<throw_if_not_implemented> {
-};
-
-#define BOOST_OPENMETHOD_DEFAULT_REGISTRY custom_registry
-
-#include <boost/openmethod.hpp>
-#include <boost/openmethod/compiler.hpp>
-
-using boost::openmethod::virtual_ptr;
-
-BOOST_OPENMETHOD_CLASSES(Animal, Cat, Dog);
-
-BOOST_OPENMETHOD(trick, (std::ostream&, virtual_ptr<Animal>), void);
-
-BOOST_OPENMETHOD_OVERRIDE(
-    trick, (std::ostream & os, virtual_ptr<Dog> /*dog*/), void) {
-    os << "spin\n";
-}
-
-auto main() -> int {
-    bom::initialize();
-
-    Cat felix;
-    Dog hector, snoopy;
-    std::vector<Animal*> animals = {&hector, &felix, &snoopy};
-
-    for (auto animal : animals) {
-        try {
-            trick(std::cout, *animal);
-        } catch (bom::not_implemented_error&) {
-            std::cout << "not implemented\n";
-        }
-    }
-
-    return 0;
-}
-
-
-
-
-
spin
-not implemented
-spin
-
-
-
-

Stock policy throw_error_handler does this for all the exception types:

-
-
-
-
namespace boost::openmethod::policies {
-
-struct throw_error_handler : error_handler {
-    template<class Error>
-    [[noreturn]] static auto error(const Error& error) -> void {
-        throw error;
-    }
-};
-
-} // namespace boost::openmethod::policies
-
-
-
-
-

Custom RTTI

-
-

Stock policies use the std_rtti implementation of rtti. Here is its full -source:

-
-
-
-
struct std_rtti : rtti {
-    template<class Class>
-    static constexpr auto is_polymorphic = std::is_polymorphic_v<Class>;
-
-    template<typename T>
-    static type_id static_type() {
-        return reinterpret_cast<type_id>(&typeid(T));
-    }
-
-    template<typename T>
-    static type_id dynamic_type(const T& obj) {
-        return reinterpret_cast<type_id>(&typeid(obj));
-    }
-
-    template<class Stream>
-    static void type_name(type_id type, Stream& stream) {
-        stream << reinterpret_cast<const std::type_info*>(type)->name();
-    }
-
-    static std::type_index type_index(type_id type) {
-        return std::type_index(*reinterpret_cast<const std::type_info*>(type));
-    }
-
-    template<typename D, typename B>
-    static D dynamic_cast_ref(B&& obj) {
-        return dynamic_cast<D>(obj);
-    }
-};
-
-
-
-
    -
  • -

    is_polymorphic is used to check if a class is polymorphic. This template is -required.

    -
  • -
  • -

    static_type is used by class registration, by virtual_ptr's "final" -constructs, and to format error and trace messages. T is not restricted to -the classes that appear as virtual parameters. This function is required.

    -
  • -
  • -

    dynamic_type is used to locate the v-table for an object. This function is -usually required. If only the virtual_ptr "final" constructs are used, or -if boost_openmethod_vptr is provided for all the classes in the policy, it -can be omitted.

    -
  • -
  • -

    type_name writes a representation of type to stream. It is used to format -error and trace messages. Stream is a lighweight version of std::ostream -with reduced functionality. It only supports insertion of const char*, -std::string_view, pointers and std::size_t. This function is optional; -if it is not provided, "type_id(type)" is used.

    -
  • -
  • -

    type_index returns an object that uniquely identifies a class. Some forms -of RTTI (most notably, C++'s typeid operator) do not guarantee that the -type information object for a class is unique within the same program. This -function is optional; if not provided, type is assumed to be unique, and -used as is.

    -
  • -
  • -

    dynamic_cast_ref casts obj to class D. B&& is either a lvalue reference -(possibly cv-qualified) or a rvalue reference. D has the same reference -category (and cv-qualifier if applicable) as B. This function is required -only in presence of virtual inheritance.

    -
  • -
-
-
-

Consider a custom RTTI implementation:

-
-
-
-
struct Animal {
-    Animal(unsigned type) : type(type) {
-    }
-
-    virtual ~Animal() = default;
-
-    unsigned type;
-    static constexpr unsigned static_type = 1;
-};
-
-struct Cat : Animal {
-    Cat() : Animal(static_type) {
-    }
-
-    static constexpr unsigned static_type = 2;
-};
-
-// ditto for Dog
-
-
-
-

This scheme has an interesting property: its type ids are monotonically -allocated in a small, dense range. Thus, we don’t need to hash them. We can use -them as indexes in the table of vptrs.

-
-
-

This time we are going to replace the default policy globally. First we need to -define the custom RTTI policy. We must not include -<boost/openmethod/core.hpp> or any header that includes it yet.

-
-
-

Here is the policy implementation:

-
-
-
-
namespace bom = boost::openmethod;
-
-struct custom_rtti : bom::policies::rtti {
-    template<class Registry>
-    struct fn : bom::policies::rtti::fn<Registry> {
-        template<class T>
-        static constexpr bool is_polymorphic = std::is_base_of_v<Animal, T>;
-
-        template<typename T>
-        static auto static_type() -> bom::type_id {
-            if constexpr (is_polymorphic<T>) {
-                return reinterpret_cast<bom::type_id>(T::static_type);
-            } else {
-                return nullptr;
-            }
-        }
-
-        template<typename T>
-        static auto dynamic_type(const T& obj) -> bom::type_id {
-            if constexpr (is_polymorphic<T>) {
-                return reinterpret_cast<bom::type_id>(obj.type);
-            } else {
-                return nullptr;
-            }
-        }
-    };
-};
-
-
-
-

This policy is quite minimal. It does not support virtual inheritance. It would -not produce good error or trace messages, because types would be represented by -their integer ids.

-
-
-

This time we create a policy from scratch. For that we use the basic_policy -CRTP template:

-
-
-
-
struct custom_policy : bom::registry<custom_rtti, bom::policies::vptr_vector> {
-};
-
-#define BOOST_OPENMETHOD_DEFAULT_REGISTRY custom_policy
-
-
-
-

Next, we include the main header. Because BOOST_OPENMETHOD_DEFAULT_REGISTRY is -defined, its value is used for the default policy. Then comes the usual example.

-
-
-
-
#include <iostream>
-
-#include <boost/openmethod.hpp>
-#include <boost/openmethod/compiler.hpp>
-
-using boost::openmethod::virtual_ptr;
-
-BOOST_OPENMETHOD(poke, (std::ostream&, virtual_ptr<Animal>), void);
-
-BOOST_OPENMETHOD_OVERRIDE(
-    poke, (std::ostream & os, virtual_ptr<Cat> /*cat*/), void) {
-    os << "hiss";
-}
-
-BOOST_OPENMETHOD_OVERRIDE(
-    poke, (std::ostream & os, virtual_ptr<Dog> /*dog*/), void) {
-    os << "bark";
-}
-
-BOOST_OPENMETHOD_CLASSES(Animal, Cat, Dog);
-
-auto main() -> int {
-    boost::openmethod::initialize();
-
-    std::unique_ptr<Animal> a(new Cat);
-    std::unique_ptr<Animal> b(new Dog);
-
-    poke(std::cout, *a); // prints "hiss"
-    std::cout << "\n";
-
-    poke(std::cout, *b); // prints "bark"
-    std::cout << "\n";
-
-    return 0;
-}
-
-
-
-

This programs works even if standard RTTI is disabled.

-
-
-
-

Deferred RTTI

-
-

In the previous example, the RTTI system assigns types id statically. It is more -common to allocate them using a global counter, manipulated by static -constructors. This is a problem, because static_type is used by class -registration. It may read the custom type ids before they are have been -initialized.

-
-
-

The solution is to add the deferred_static_rtti policy to the policy; it defers -reading the type information until initialize is called.

-
-
-

This time let’s support virtual inheritance as well. First the domain classes:

-
-
-
-
struct custom_type_info {
-    static unsigned last;
-    unsigned id = ++last;
-};
-
-unsigned custom_type_info::last;
-
-struct Animal {
-    Animal() {
-        type = type_info.id;
-    }
-
-    virtual ~Animal() = default;
-
-    virtual auto cast_impl(unsigned target) -> void* {
-        if (type_info.id == target) {
-            return this;
-        } else {
-            return nullptr;
-        }
-    }
-
-    template<class Class>
-    auto cast() -> Class* {
-        return reinterpret_cast<Class*>(cast_impl(Class::type_info.id));
-    }
-
-    static custom_type_info type_info;
-    unsigned type;
-};
-
-custom_type_info Animal::type_info;
-
-struct Cat : virtual Animal {
-    Cat() {
-        type = type_info.id;
-    }
-
-    virtual auto cast_impl(unsigned target) -> void* {
-        if (type_info.id == target) {
-            return this;
-        } else {
-            return Animal::cast_impl(target);
-        }
-    }
-
-    static custom_type_info type_info;
-};
-
-custom_type_info Cat::type_info;
-// ditto for Dog
-
-
-
-

The rtti policy is the same, with one more function:

-
-
-
-
struct custom_rtti : bom::policies::rtti {
-    // as before
-
-        // to support virtual inheritance:
-        template<typename Derived, typename Base>
-        static auto dynamic_cast_ref(Base&& obj) -> Derived {
-            using base_type = std::remove_reference_t<Base>;
-            if constexpr (std::is_base_of_v<Animal, base_type>) {
-                return *obj.template cast<std::remove_reference_t<Derived>>();
-            } else {
-                abort(); // not supported
-            }
-        }
-};
-
-
-
-

Finally, the policy contains an additional policy - deferred_static_rtti:

-
-
-
-
struct custom_policy
-    : bom::policies::basic_policy<
-          custom_policy, custom_rtti,
-          bom::policies::deferred_static_rtti, // <-- additional policy
-          bom::policies::vptr_vector<custom_policy>> {};
-
-
-
-

The example is the same as in the previous section.

-
-
-
-

Dynamic Loading

-
-

OpenMethod supports dynamic loading on operating systems that are capable of -handling C++ templates correctly during dynamic link. A dynamic library can add -classes, methods and overriders to an existing policy. initialize must then be -called to rebuild the dispatch tables.

-
-
-

This leads to a problem: any virtual_ptr in existence before initialize is -called again becomes invalid. This also applies to vptrs that are stored inside -objects by inplace_vptr.

-
-
- - - - - -
-
Note
-
-This applies only to cases where a dynamic library adds to an existing -policy. Even if the dynamic library itself uses open-methods, for example as an -implementation detail, but it uses its own policy, there is no issue. -
-
-
-

The solution is to use a policy that contains the indirect_vptr policy. Instead -of storing the vptr directly, it stores a reference to the vptr.

-
-
-

Here is an example:

-
-
-
-
// dl.hpp
-
-#include <string>
-
-#include <boost/openmethod.hpp>
-
-struct Animal {
-    virtual ~Animal() {
-    }
-};
-
-struct Herbivore : Animal {};
-struct Carnivore : Animal {};
-struct Cow : Herbivore {};
-struct Wolf : Carnivore {};
-
-struct dynamic : boost::openmethod::default_registry::with<
-                            boost::openmethod::policies::indirect_vptr> {};
-
-template<class Class>
-using dyn_vptr = boost::openmethod::virtual_ptr<Class, dynamic>;
-
-BOOST_OPENMETHOD(
-    encounter, (dyn_vptr<Animal>, dyn_vptr<Animal>), std::string,
-    dynamic);
-
-
-
- - - - - -
-
Note
-
-The policy must be passed to the method as well as the -virtual_ptrs. -
-
-
-

The indirect_vptr policy tells virtual_ptr to use a pointer to the vptr. Even -tough the value of the vptr changes when initialize is called, the vptrs are -stored in the same place (the policy’s static_vptr<Class> variables).

-
-
-

We can now register the classes and and provide an overrider:

-
-
-
-
// dl_main.cpp
-
-#include <cstring>
-#include <iostream>
-#include <dlfcn.h>
-#include <unistd.h>
-
-#include <boost/openmethod.hpp>
-#include <boost/openmethod/interop/std_unique_ptr.hpp>
-#include <boost/openmethod/compiler.hpp>
-
-#include "dl.hpp"
-
-BOOST_OPENMETHOD_CLASSES(
-    Animal, Herbivore, Cow, Wolf, Carnivore, dynamic);
-
-BOOST_OPENMETHOD_OVERRIDE(
-    encounter, (dyn_vptr<Animal>, dyn_vptr<Animal>), std::string) {
-    return "ignore\n";
-}
-
-
-
-

At this point we only have one overrider. Animals of all species ignore one -another:

-
-
-
-
auto main() -> int {
-    using namespace boost::openmethod;
-
-    initialize<dynamic>();
-
-    std::cout << "Before loading library\n";
-
-    auto gracie = make_unique_virtual<Cow, dynamic>();
-    // Wolf _willy;
-    // auto willy = virtual_ptr<Wolf, dynamic>(_willy);
-    auto willy = make_unique_virtual<Wolf, dynamic>();
-
-    std::cout << "Gracie encounters Willy -> "
-              << encounter(gracie, willy); // ignore
-    std::cout << "Willy encounters Gracie -> "
-              << encounter(willy, gracie); // ignore
-
-
-
-

Let’s load a dynamic library containing this code:

-
-
-
-
// dl_shared.cpp
-
-#include <string>
-#include <boost/openmethod.hpp>
-
-#include "dl.hpp"
-
-BOOST_OPENMETHOD_OVERRIDE(
-    encounter, (dyn_vptr<Herbivore>, dyn_vptr<Carnivore>), std::string) {
-    return "run\n";
-}
-
-struct Tiger : Carnivore {};
-
-BOOST_OPENMETHOD_CLASSES(Tiger, Carnivore, dynamic);
-
-extern "C" auto make_tiger() -> Tiger* {
-    return new Tiger;
-}
-
-BOOST_OPENMETHOD_OVERRIDE(
-    encounter, (dyn_vptr<Carnivore>, dyn_vptr<Herbivore>), std::string) {
-    return "hunt\n";
-}
-
-
-
-

Now back to main:

-
-
-
-
    char dl_path[4096];
-    dl_path[readlink("/proc/self/exe", dl_path, sizeof(dl_path))] = 0;
-    *strrchr(dl_path, '/') = 0;
-    strcat(dl_path, "/libdl_shared.so");
-    void* handle = dlopen(dl_path, RTLD_NOW);
-
-    if (!handle) {
-        std::cerr << "dlopen() failed: " << dlerror() << "\n";
-        exit(1);
-    }
-
-    std::cout << "\nAfter loading library\n";
-
-    boost::openmethod::initialize<dynamic>();
-
-    auto make_tiger =
-        reinterpret_cast<Animal* (*)()>(dlsym(handle, "make_tiger"));
-
-    if (!make_tiger) {
-        std::cerr << "dlsym() failed: " << dlerror() << "\n";
-        exit(1);
-    }
-
-    std::cout << "Willy encounters Gracie -> "
-              << encounter(willy, gracie); // hunt
-
-    {
-        auto hobbes = std::unique_ptr<Animal>(make_tiger());
-        std::cout << "Gracie encounters Hobbes -> "
-                  << encounter(gracie, *hobbes); // run
-    }
-
-
-
-

After unloading the library, we must call initialize again:

-
-
-
-
    dlclose(handle);
-
-    std::cout << "\nAfter unloading library\n";
-
-    boost::openmethod::initialize<dynamic>();
-
-    std::cout << "Gracie encounters Willy -> "
-              << encounter(gracie, willy); // ignore
-    std::cout << "Willy encounters Gracie -> "
-              << encounter(willy, gracie); // ignore
-
-
-
-
-
-
-

Reference

-
-
-

Overview

-
-

Requirements

-
-

OpenMethod requires C++17 or above. It depends on the following Boost libraries:

-
-
-
    -
  • -

    Assert

    -
  • -
  • -

    Config

    -
  • -
  • -

    Core

    -
  • -
  • -

    DynamicBitset

    -
  • -
  • -

    Mp11

    -
  • -
  • -

    Preprocessor

    -
  • -
-
-
-

Boost.Test is also required to build and run the unit tests.

-
-
-
-

Installation

-
-

The library is headers-only. You can install it system-wide, or add the path to -the include directory to your project’s include path.

-
-
-
-

Namespaces

-
-
boost::openmethod
-
-

The library’s main namespace. Contains method, virtual_ptr and -virtual_ptr_traits, use_classes, the default_registry, etc.

-
-
-
-
boost::openmethod::policies
-
-

Contains the policy framework.

-
-
-
-
-

Headers

-
-
<boost/openmethod/core.hpp>
-
-

The library’s main header. Provides method, virtual_ptr and -virtual_ptr_traits, use_classes, the default policy, etc.

-
-
-

If BOOST_OPENMETHOD_DEFAULT_REGISTRY is defined before including this header, -its value is used as the default value for the Policy template parameter -throughout the code. Otherwise, boost::openmethod::default_registry is used. -Setting BOOST_OPENMETHOD_DEFAULT_REGISTRY after including the core header has no -effect.

-
-
-
-
<boost/openmethod/macros.hpp>
-
-

Provides BOOST_REGISTER_CLASSES, BOOST_OPENMETHOD, -BOOST_OPENMETHOD_OVERRIDE and other macros.

-
-
-
-
<boost/openmethod.hpp>
-
-

Convenience header. Includes <boost/openmethod/core.hpp> and -<boost/openmethod/macros.hpp>.

-
-
-

Also imports boost::openmethod::virtual_ptr in the global namespace. This is -usually regarded as bad practice. The rationale is that OpenMethod emulates a -language feature, and virtual_ptr is equivalent to keyword, similar to -virtual. Besides, the macros are global as well.

-
-
-

There are two ways to avoid importing virtual_ptr while still using the -macros:

-
-
-
    -
  • -

    Define BOOST_OPENMETHOD_NO_GLOBAL_VIRTUAL_PTR before including -<boost/openmethod.hpp>. This disables the import of virtual_ptr in the -global namespace.

    -
  • -
  • -

    Include <boost/openmethod/core.hpp>`and `<boost/openmethod/macros.hpp>.

    -
  • -
-
-
-
-
<boost/openmethod/compiler.hpp>
-
-

Provides intialize and finalize. Typically included only by the translation -unit that contains main, unless dynamic loading is used in other places in the -program.

-
-
-
-
<boost/openmethod/interop/std_shared_ptr.hpp>
-
-

Provides support for using std::shared_ptr in place of plain pointers in -virtual parameters.

-
-
-
-
<boost/openmethod/unique_.hpp>
-
-

Provides support for using std::unique_ptr in place of plain pointers in -virtual parameters.

-
-
-
-
<boost/openmethod/inplace_vptr.hpp>
-
-

Provides support for storing v-table pointers directly in objects, in the same -manner as native virtual functions.

-
-
-
-
<boost/openmethod/policies.hpp>
-
-

Provides the debug and release policies in the boost::openmethod::policies -namespace, and default_registry in the boost::openmethod namespace, which is -an alias to either debug or release, depending on the value of the -preprocessor symbol NDEBUG.

-
-
-

Usually not included directly. Can be used to create custom policies from stock -policies, by forking them and adjusting a few policys.

-
-
-
-
<boost/openmethod/policies/basic_policy.hpp>
-
-

Provides the constructs used in the policy framework, essentially -basic_policy, policy, and its abstract subclasses (rtti, extern_vptr, -etc).

-
-
-
-
<boost/openmethod/policies/std_rtti.hpp>
-
-

Implements the rtti policy using standard RTTI.

-
-
-
-
<boost/openmethod/policies/minimal_rtti.hpp>
-
-

Implements the rtti policy using a minimal RTTI implementation. Can be used only with the "final" constructs, or with intrusive v-table pointers.

-
-
-
-
<boost/openmethod/policies/vptr_vector.hpp>
-
-

Implements the extern_vptr policy using a vector of pointers.

-
-
-
-
<boost/openmethod/policies/vptr_map.hpp>
-
-

Implements the extern_vptr policy using a map of pointers.

-
-
-
-
<boost/openmethod/policies/fast_perfect_hash.hpp>
-
-

Implements the type_hash policy using a perfect hash function.

-
-
-
-
<boost/openmethod/policies/default_error_handler.hpp>
-
-

Implements the error_handler policy by routing the error through a -std::function.

-
-
-
-
<boost/openmethod/policies/throw_error_handler.hpp>
-
-

Implements the error_handler policy by throwing an exception.

-
-
-
-
<boost/openmethod/policies/basic_error_output.hpp>
-
-

Implements the output policy using a lightweight version of -std::ostream.

-
-
-
-
<boost/openmethod/policies/basic_trace_output.hpp>
-
-

Implements the trace policy using a lightweight version of -std::ostream.

-
-
-
-
-
-

BOOST_OPENMETHOD

-
-

Synopsis

-
-

Defined in <boost/openmethod/macros.hpp>.

-
-
-
-
BOOST_OPENMETHOD(NAME, (PARAMETERS...), RETURN_TYPE [, POLICY]);
-
-
-
-
-

Description

-
-

Declares a method.

-
-
-

The macro expands to several constructs:

-
-
-
    -
  • -

    A struct forward declaration that acts as the method’s identifier:

    -
  • -
-
-
-
-
struct BOOST_OPENMETHOD_ID(NAME);
-
-
-
-
    -
  • -

    An inline function template, constrained to take the same PARAMETERS, -without the virtual_ decorators, returning a RETURN_TYPE. The function -forwards to
    -method<BOOST_OPENMETHOD_ID(NAME)(PARAMETERS…​), RETURN_TYPE, POLICY>::fn.

    -
  • -
  • -

    A guide function used to match overriders with the method:

    -
  • -
-
-
-
-
auto BOOST_OPENMETHOD_ID(NAME)_guide(...)
-    -> ::boost::openmethod::method<
-        BOOST_OPENMETHOD_ID(NAME)(PARAMETERS...), RETURN_TYPE [, POLICY]>;
-
-
-
- - - - - -
-
Note
-
-NAME must be an identifier. Qualified names are not allowed. -
-
-
- - - - - -
-
Note
-
-The default value for POLICY is the value of -BOOST_OPENMETHOD_DEFAULT_REGISTRY at the point <boost/openmethod/core.hpp> is -included. Changing the value of this symbol has no effect after that point. -
-
-
-
-
-

BOOST_OPENMETHOD_OVERRIDE

-
-

Synopsis

-
-

Defined in <boost/openmethod/macros.hpp>.

-
-
-
-
BOOST_OPENMETHOD_OVERRIDE(NAME, (PARAMETERS...), RETURN_TYPE) {
-    // body
-}
-
-
-
-
-

Description

-
-

BOOST_OPENMETHOD_OVERRIDE adds an overrider to a method.

-
-
-

The method is deduced from a call to a method guide function with the -overrider’s arguments.

-
-
-

The macro creates several entities in the current scope.

-
-
-
    -
  • -

    A class template that acts as a container for the overriders of the methods -called NAME:

    -
  • -
-
-
-
-
template<typename...> BOOST_OPENMETHOD_OVERRIDERS(NAME);
-
-
-
-
    -
  • -

    A specialization of the container template for the overrider:

    -
  • -
-
-
-
-
struct BOOST_OPENMETHOD_OVERRIDERS(NAME)<RETURN_TYPE(PARAMETERS...)> {
-    static auto fn(PARAMETERS...) -> RETURN_TYPE;
-    static auto has_next() -> bool;
-    template<typename... Args>
-    static auto next(typename... Args) -> RETURN_TYPE;
-};
-
-
-
-

where:

-
-
-
    -
  • -

    fn is the overrider function.

    -
  • -
  • -

    has_next() returns true if a less specialized overrider exists.

    -
  • -
  • -

    next(Args…​ args) calls the next most specialized overrider via the -pointer stored in the method’s next<fn> member variable.

    -
  • -
-
-
-

Finally, the macro starts the definition of the overrider function:

-
-
-
-
auto BOOST_OPENMETHOD_OVERRIDERS(NAME)<RETURN_TYPE(PARAMETERS...)>::fn(
-    PARAMETERS...) -> RETURN_TYPE
-
-
-
-

The block following the call to the macro is the body of the function.

-
-
- - - - - -
-
Note
-
-NAME must be an identifier. Qualified names are not allowed. -
-
-
-
-
-

BOOST_OPENMETHOD_INLINE_OVERRIDE

-
-

Synopsis

-
-

Defined in <boost/openmethod/macros.hpp>.

-
-
-
-
BOOST_OPENMETHOD_INLINE_OVERRIDE(NAME, (PARAMETERS...), RETURN_TYPE) {
-    // body
-}
-
-
-
-
-

Description

-
-

BOOST_OPENMETHOD_INLINE_OVERRIDE performs the same function as -BOOST_OPENMETHOD_OVERRIDE, except that the overrider is defined inline.

-
-
- - - - - -
-
Note
-
-NAME must be an identifier. Qualified names are not allowed. -
-
-
-
-
-

BOOST_OPENMETHOD_DECLARE_OVERRIDER

-
-

Synopsis

-
-

Defined in <boost/openmethod/macros.hpp>.

-
-
-
-
#define BOOST_OPENMETHOD_DECLARE_OVERRIDER(NAME, (PARAMETERS...), RETURN_TYPE)
-
-
-
-
-

Description

-
-

Declares an overrider for a method.

-
-
-

The method is deduced from a call to a method guide function with the -overrider’s arguments.

-
-
-

The macro creates several entities in the current scope.

-
-
-
    -
  • -

    A class template that acts as a container for the overriders of the methods -called NAME:

    -
  • -
-
-
-
-
template<typename...> BOOST_OPENMETHOD_OVERRIDERS(NAME);
-
-
-
-
    -
  • -

    A specialization of the container template for the overrider:

    -
  • -
-
-
-
-
struct BOOST_OPENMETHOD_OVERRIDERS(NAME)<RETURN_TYPE(PARAMETERS...)> {
-    static auto fn(PARAMETERS...) -> RETURN_TYPE;
-    static auto has_next() -> bool;
-    template<typename... Args>
-    static auto next(typename... Args) -> RETURN_TYPE;
-};
-
-
-
-

where:

-
-
-
    -
  • -

    fn is the overrider function.

    -
  • -
  • -

    has_next() returns true if a less specialized overrider exists.

    -
  • -
  • -

    next(Args…​ args) calls the next most specialized overrider via the -pointer stored in the method’s next<fn> member variable.

    -
  • -
-
-
-

BOOST_OPENMETHOD_DECLARE_OVERRIDER can be called in a header file, with a -semicolon after the call. It can be called in a header file, but not multiple -times in the same translation unit.

-
-
- - - - - -
-
Note
-
-NAME must be an identifier. Qualified names are not allowed. -
-
-
-
-
-

BOOST_OPENMETHOD_DEFINE_OVERRIDER

-
-

Synopsis

-
-

Defined in <boost/openmethod/macros.hpp>.

-
-
-
-
#define BOOST_OPENMETHOD_DEFINE_OVERRIDER(NAME, (PARAMETERS...), RETURN_TYPE)
-
-
-
-
-

Description

-
-

Defines the body of an overrider declared with -BOOST_OPENMETHOD_DECLARE_OVERRIDER. It should be called in an implementation -file, and followed by a function body.

-
-
- - - - - -
-
Note
-
-NAME must be an identifier. Qualified names are not allowed. -
-
-
-
-
-

BOOST_OPENMETHOD_OVERRIDER

-
-

Synopsis

-
-

Defined in <boost/openmethod/macros.hpp>.

-
-
-
-
#define BOOST_OPENMETHOD_OVERRIDER(NAME, (PARAMETERS...), RETURN_TYPE)
-
-
-
-
-

Description

-
-

Expands to the specialization of the class template that contains the overrider -for with the given name, parameter list and return type.

-
-
-
-
-

BOOST_OPENMETHOD_ID

-
-

Synopsis

-
-

Defined in <boost/openmethod/macros.hpp>.

-
-
-
-
#define BOOST_OPENMETHOD_ID(NAME) /* unspecified */
-
-
-
-
-

Description

-
-

Generates a long, obfuscated name from a short name. All the other names -generated by macros are based on this name.

-
-
-
-
-

BOOST_OPENMETHOD_GUIDE

-
-

Synopsis

-
-

Defined in <boost/openmethod/macros.hpp>.

-
-
-
-
#define BOOST_OPENMETHOD_GUIDE(NAME) /* unspecified */
-
-
-
-
-

Description

-
-

Expands to the name of the guide function used to match overriders to methods.

-
-
-
-
-

BOOST_OPENMETHOD_OVERRIDERS

-
-

Synopsis

-
-

Defined in <boost/openmethod/macros.hpp>.

-
-
-
-
#define BOOST_OPENMETHOD_OVERRIDERS(NAME)                                      \
-    BOOST_PP_CAT(BOOST_OPENMETHOD_ID(NAME), _overriders)
-
-
-
-
-

Description

-
-

BOOST_OPENMETHOD_OVERRIDERS expands to the name of the class template that -contains the overriders for all the methods with a given name.

-
-
-
-
-

BOOST_OPENMETHOD_REGISTER

-
-

Synopsis

-
-

Defined in <boost/openmethod/macros.hpp>.

-
-
-
-
BOOST_OPENMETHOD_REGISTER(TYPE);
-
-
-
-
-

Description

-
-

Creates a static instance of TYPE, using a unique generated name.

-
-
-
-
-

BOOST_OPENMETHOD_CLASSES

-
-

Synopsis

-
-

Defined in <boost/openmethod/macros.hpp>.

-
-
-
-
BOOST_OPENMETHOD_CLASSES(CLASSES...[, POLICY]);
-
-
-
-
-

Description

-
-

Register CLASSES in POLICY.

-
-
- - - - - -
-
Note
-
-The default value for POLICY is the value of -BOOST_OPENMETHOD_DEFAULT_REGISTRY when <boost/openmethod/core.hpp> is -included. Subsequently changing it has no retroactive effect. -
-
-
-

This macro is a wrapper around use_classes; see its documentation for more -details.

-
-
-
-
-

BOOST_OPENMETHOD_DEFAULT_REGISTRY

-
-

Description

-
-

The name of the default policy.

-
-
-

BOOST_OPENMETHOD_DEFAULT_REGISTRY is the default value for the Policy template -parameter of method, use_classes, and other constructs defined in -<boost/openmethod/core.hpp>. If it is not defined, -::boost::openmethod::policy::default_registry is used.

-
-
-

BOOST_OPENMETHOD_DEFAULT_REGISTRY can be defined by a program to change the -default policy globally. Once <boost/openmethod/core.hpp> has been included, -redefining the symbol has no effect. To override the default policy, proceed as -follows:

-
-
-
    -
  1. -

    Include headers under boost/openmethod/policies/ as needed.

    -
  2. -
  3. -

    Create a policy class, and set BOOST_OPENMETHOD_DEFAULT_REGISTRY.

    -
  4. -
  5. -

    Include <boost/openmethod/core.hpp>.

    -
  6. -
-
-
-
-
-

initialize

-
-

Synopsis

-
-

Defined in <boost/openmethod/compiler.hpp>.

-
-
-
-
namespace boost::openmethod {
-
-template<class Policy = BOOST_OPENMETHOD_DEFAULT_REGISTRY>
-auto initialize() -> /*unspecified*/;
-
-}
-
-
-
-
-

Description

-
-

Initializes dispatch data for the methods registered in Policy. This function -must be called before any calls to those methods, and after loading or unloading -a dynamic library that adds classes, methods or overriders to Policy.

-
-
-

The return value is an object that contains a member variable, report, that -contains the following information:

-
-
-
    -
  • -

    std::size_t cells: the number of cells used by the v-tables and the multiple -dispatch tables.

    -
  • -
  • -

    std::size_t not_implemented: the number of methods that don’t have an -overrider for at least one combination of virtual arguments.

    -
  • -
  • -

    std::size_t ambiguous: the number of methods that have more than one -overrider, none of which is more specific than the others, for at least one -combination of virtual arguments.

    -
  • -
-
-
-
-
-

finalize

-
-

Synopsis

-
-

Defined in <boost/openmethod/compiler.hpp>.

-
-
-
-
namespace boost::openmethod {
-
-template<class Policy = BOOST_OPENMETHOD_DEFAULT_REGISTRY>
-auto finalize() -> void;
-
-}
-
-
-
-
-

Description

-
-

De-allocates the resources allocated by initialize for the Policy, including -resources allocated by the policys in Policy. Resources are de-allocated in an -arbitrary order. It is not necessary to call finalize between calls to -initialize. It is provided mainly for the benefit of memory leak detection -schemes.

-
-
-
-
-

type_id

-
-

Synopsis

-
-

Defined in <boost/openmethod/policies/basic_policy.hpp>.

-
-
-
-
namespace boost::openmethod {
-
-using type_id = std::uintptr_t;
-
-}
-
-
-
-
-

Description

-
-

type_id is an unsigned integer type used to identify types. It is wide enough -to contain a pointer.

-
-
-
-
-

vptr_type

-
-

Synopsis

-
-

Defined in <boost/openmethod/policies/basic_policy.hpp>.

-
-
-
-
namespace boost::openmethod {
-
-using vptr_type = const /*unspecified*/ *;
-
-}
-
-
-
-
-

Description

-
-

vptr_type is the type of a pointer to a v-table.

-
-
-
-
-

method

-
-

Synopsis

-
-
-
namespace boost::openmethod {
-
-template<
-    typename Method, typename ReturnType,
-    class Policy = BOOST_OPENMETHOD_DEFAULT_REGISTRY>
-class method;
-
-template<typename Name, typename... Parameters, typename ReturnType, class Policy>
-class method<Name(Parameters...), ReturnType, Policy> {
-  public:
-    using function_type = ReturnType (*)(CallParameters...);
-
-    auto operator()(CallParameters... args) const -> ReturnType;
-
-    static method fn;
-
-    template<auto... Functions>
-    struct override;
-
-    template<auto Overrider>
-    static function_type next;
-
-  private:
-    method();
-    method(const method&) = delete;
-    method(method&&) = delete;
-    ~method();
-};
-
-}
-
-
-
-
-

Description

-
-

method implements an open-method that takes a parameter list - Parameters - -and returns a ReturnType. Name can be any type. Its purpose is to make it -possible to have multiple methods with the same signature. Typically, Name is -a class whose name reflects the method’s purpose.

-
-
-

Parameters must contain at least one virtual parameter, i.e. a parameter that -has a type in the form virtual_ptr<T, Policy> or virtual_<T>. The -dynamic types of the virtual arguments (the arguments corresponding to virtual -parameters in the method’s signature) are taken into account to select the -overrider to call.

-
-
-

A method is attached to a Policy, which influences several parts of the -dispatch mechanism - for example, how to obtain a v-table pointer for an object, -how to report errors, whether to perform sanity checks, etc.

-
-
-
-

Members

-
-
constructor
-
-
-
method();
-
-
-
-

Add the method to the list of methods registered in Policy.

-
-
-

The constructor is private. The only instance is the static member variable -fn.

-
-
-
-
destructor
-
-
-
~method();
-
-
-
-

Remove the method from the list of methods registered in Policy.

-
-
-
-
operator()
-
-
-
auto operator()(CallParameters... args) const -> ReturnType;
-
-
-
-

Call the method with the arguments args.

-
-
-

CallParameters are the Parameters without the virtual_ decorators. Note -that virtual_ptrs are preserved.

-
-
-

The overrider is selected in a process similar to overloaded function -resolution, with extra rules to handle ambiguities. It proceeds as follows:

-
-
-
    -
  1. -

    Form the set of all applicable overriders. An overrider is applicable if it -can be called with the arguments passed to the method.

    -
  2. -
  3. -

    If the set is empty, call the error handler (if present in the policy), then -terminate the program with abort

    -
  4. -
  5. -

    Remove the overriders that are dominated by other overriders in the set. -Overrider A dominates overrider B if any of its virtual formal parameters is -more specialized than B’s, and if none of B’s virtual parameters is more -specialized than A’s.

    -
  6. -
  7. -

    If the resulting set contains only one overrider, call it.

    -
  8. -
  9. -

    If the return type is a registered polymorphic type, remove all the -overriders that return a less specific type than the others.

    -
  10. -
  11. -

    If the resulting set contains only one overrider, call it.

    -
  12. -
  13. -

    Otherwise, call one of the remaining overriders. Which overrider is selected -is not specified, but it is the same across calls with the same arguments -types.

    -
  14. -
-
-
-

For each virtual argument arg, the dispatch mechanism calls -virtual_traits::peek(arg) and deduces the v-table pointer from the result, -using the first of the following methods that applies:

-
-
-
    -
  1. -

    If result is a virtual_ptr, get the pointer to the v-table from it.

    -
  2. -
  3. -

    If a function named boost_openmethod_vptr that takes result and returns a -vptr_type exists, call it.

    -
  4. -
  5. -

    Call Policy::dynamic_vptr(result).

    -
  6. -
-
-
-
-
fn
-
-
-
static method fn;
-
-
-
-

The method's unique instance. The method is called via the call -operator on fn: method::fn(args…​).

-
-
-
-
override
-
-
-
template<auto... Functions>
-struct override;
-
-
-
-

Add Functions to the overriders of method.

-
-
-
-
next
-
-
-
template<auto Overrider>
-static function_type next;
-
-
-
-

Pointer to the next most specialized overrider after Overrider, i.e. the -overrider that would be called for the same tuple of virtual arguments if -Overrider was not present. Set to nullptr if no such overrider exists.

-
-
-
-
-
-

method::override

-
-

Synopsis

-
-
-
namespace boost::openmethod {
-
-template<typename Signature, typename ReturnType, class Policy>
-template<auto... Functions>
-struct method<Signature, ReturnType, Policy>::override {
-    override();
-    ~override();
-};
-
-}
-
-
-
-

Usage:

-
-
-
-
method<Signature, ReturnType, Policy>::override<Functions...> some_unique_name;
-  // at file scope
-
-
-
-
-

Description

-
-

override, instantiated as a static object, add one or more overriders to an -open-method.

-
-
-

Functions must fulfill the following requirements:

-
-
-
    -
  • -

    Have the same number of formal parameters as the method.

    -
  • -
  • -

    Each parameter in the same position as a virtual_ptr<T> in the method’s -parameter list must be a virtual_ptr<U>, where U is covariant with T. The -Policy of the virtual_ptrs must be the same as the method’s Policy.

    -
  • -
  • -

    Each formal parameter in the same position as a virtual_ parameter must have -a type that is covariant with the type of the method’s parameter.

    -
  • -
  • -

    All other formal parameters must have the same type as the method’s -corresponding parameters.

    -
  • -
  • -

    The return type of the overrider must be the same as the method’s return type -or, if it is a polymorphic type, covariant with the method’s return type.

    -
  • -
-
-
-
-

Members

-
-
constructor
-
-
-
override<Functions>::override();
-
-
-
-

Add Functions to the overriders of method.

-
-
-
-
Destructor
-
-
-
override<Functions>::~method();
-
-
-
-

Remove Functions from the overriders of method.

-
-
-
-
-
-

virtual_ptr

-
-

Synopsis

-
-

virtual_ptr is defined in <boost/openmethod/core.hpp>.

-
-
-
-
namespace boost::openmethod {
-
-template<class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_REGISTRY>
-class virtual_ptr {
-  public:
-    static constexpr bool is_smart_ptr = /* see below */;
-    using element_type = /* see below */;
-
-    virtual_ptr();
-    virtual_ptr(nullptr_t);
-    template<class Other> virtual_ptr(Other& other);
-    template<class Other> virtual_ptr(const Other& other);
-    template<class Other> virtual_ptr(Other&& other);
-
-    virtual_ptr& operator =(nullptr_t);
-    template<class Other> virtual_ptr& operator =(Other& other);
-    template<class Other> virtual_ptr& operator =(const Other& other);
-    template<class Other> virtual_ptr& operator =(Other&& other);
-
-    template<class Other>
-    static auto final(Other&& obj);
-
-    auto get() const -> element_type*;
-    auto operator->() const -> element_type*;
-    auto operator*() const -> element_type&;
-    auto pointer() const -> const Class*&;
-
-    template<typename Other>
-    auto cast() const -> virtual_ptr<Other, Policy>;
-};
-
-template<class Class>
-virtual_ptr(Class&) -> virtual_ptr<Class, BOOST_OPENMETHOD_DEFAULT_REGISTRY>;
-
-template<class Class>
-inline auto final_virtual_ptr(Class& obj) -> virtual_ptr<
-    Class, BOOST_OPENMETHOD_DEFAULT_REGISTRY>;
-
-template<class Policy, class Class>
-inline auto final_virtual_ptr(Class& obj) -> virtual_ptr<Class, Policy>;
-
-template<class Left, class Right, class Policy>
-auto operator==(
-    const virtual_ptr<Left, Policy>& left,
-    const virtual_ptr<Right, Policy>& right) -> bool;
-
-template<class Left, class Right, class Policy>
-auto operator!=(
-    const virtual_ptr<Left, Policy>& left,
-    const virtual_ptr<Right, Policy>& right) -> bool;
-
-} // namespace boost::openmethod
-
-
-
-

Defined in <boost/openmethod/interop/std_shared_ptr.hpp>:

-
-
-
-
namespace boost::openmethod {
-
-template<class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_REGISTRY>
-using shared_virtual_ptr = virtual_ptr<std::shared_ptr<Class>, Policy>;
-
-template<
-    class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_REGISTRY, typename... T>
-inline auto make_shared_virtual(T&&... args)
-    -> shared_virtual_ptr<Class, Policy>;
-
-}
-
-
-
-

Defined in <boost/openmethod/interop/std_unique_ptr.hpp>:

-
-
-
-
namespace boost::openmethod {
-
-template<class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_REGISTRY>
-using unique_virtual_ptr = virtual_ptr<std::unique_ptr<Class>, Policy>;
-
-template<
-    class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_REGISTRY, typename... T>
-inline auto make_unique_virtual(T&&... args)
-    -> unique_virtual_ptr<Class, Policy>;
-}
-
-
-
-
-

Description

-
-

virtual_ptr is a wide pointer that combines a pointer to an object and a -pointer to its v-table. The object pointer can be a plain pointer or a smart -pointer. Specializations of virtual_traits are required for smart pointers. -They are provided for std::unique_ptr and std::shared_ptr.

-
-
-

A plain virtual_ptr can be constructed from a reference, a smart pointer, or -another virtual_ptr. A smart virtual_ptr can be constructed from a smart -pointer or from a smart virtual_ptr. Usual conversions - from derived to base, -and from non-const to const - are supported.

-
-
-
-

Members

-
-
is_smart_ptr
-
-
-
static constexpr bool is_smart_ptr;
-
-
-
-

true if Class is a smart pointer, false otherwise. The value is derived -from virtual_traits<Class, Policy>: if it has a member template called -rebind, Class is considered a smart pointer.

-
-
-
-
element_type
-
-
-
using element_type = std::conditional_t<
-    is_smart_ptr, typename Class::element_type, Class>;
-
-
-
-

The class of the object pointed to.

-
-
-
-
constructors
-
-
-
virtual_ptr();                                          // 1
-virtual_ptr(nullptr_t);                                 // 2
-template<class Other> virtual_ptr(Other& other);        // 3
-template<class Other> virtual_ptr(const Other& other);  // 4
-template<class Other> virtual_ptr(Other&& other);       // 5
-template<class Other> virtual_ptr(Other* other);        // 6
-
-
-
-

(1) Default constructor. Sets the v-table pointer to nullptr. If Class is -not a smart pointer, the value of object pointer is is undefined.

-
-
-

(2) Sets both the object and v-table pointers to nullptr.

-
-
-

(3), (4) For plain virtual_ptrs, other must be either a lvalue -reference to an object of a registered class, or a virtual_ptr (plain or -smart). For smart virtual_ptrs, other must be a reference to a smart -pointer, or a reference to a smart virtual_ptr.

-
-
-

(5) Constructs a virtual_ptr from a smart pointer or a smart virtual_ptr. -The object pointer is moved from other.

-
-
-

(6) Constructs a virtual_ptr from a plain pointer. Available only for plain -virtual_ptrs.

-
-
-

If other is also a virtual_ptr, the v-table pointer is copied from it. -Otherwise, it is deduced from the object. The Policy must be the same for both -virtual_ptrs.

-
-
-
-
assignment operators
-
-
-
virtual_ptr& operator =(nullptr_t);                                 // 1
-template<class Other> virtual_ptr& operator =(Other& other);        // 2
-template<class Other> virtual_ptr& operator =(const Other& other);  // 3
-template<class Other> virtual_ptr& operator =(Other&& other);       // 4
-template<class Other> virtual_ptr& operator =(Other* other);        // 5
-
-
-
-

(1) Sets both the object and v-table pointers to nullptr.

-
-
-

(2), (3) For plain virtual_ptrs, other must be either a lvalue -reference to an object of a registered class, or a virtual_ptr (plain or -smart). For smart virtual_ptrs, other must be a reference to a smart -pointer, or a reference to a smart virtual_ptr.

-
-
-

(4) Moves other to this virtual_ptr. If other is a smart pointer or a -smart virtual pointer, the object pointer is moved from other.

-
-
-

(5) Sets the object pointer to other. Available only for plain -virtual_ptrs.

-
-
-

If other is also a virtual_ptr, the v-table pointer is copied from it. -Otherwise, it is deduced from the object. The Policy must be the same for both -virtual_ptrs.

-
-
-
-
final
-
-
-
template<class Other>
-static auto final(Other&& obj);
-
-
-
-

Constructs a virtual_ptr from a reference to an object, or from a smart -pointer. It is assumed that the static and dynamic types are the same. The -v-table pointer is initialized from the Policy::static_vptr for the class, -which needs not be polymorphic.

-
-
-
-
get
-
-
-
auto get() const -> element_type*;
-
-
-
-

Returns a pointer to the object.

-
-
-
-
operator→
-
-
-
auto operator->() const -> element_type*;
-
-
-
-

Returns a pointer to the object.

-
-
-
-
operator*
-
-
-
auto operator*() const -> element_type&;
-
-
-
-

Returns a reference to the object.

-
-
-
-
pointer
-
-
-
auto pointer() const;
-
-
-
-

Returns a reference to the object pointer, which can be either a plain pointer -or a smart pointer.

-
-
-
-
cast
-
-
-
template<typename Other>
-auto cast() const -> virtual_ptr<Other, Policy>;
-
-
-
-

Returns a virtual_ptr to the same object, cast to Other.

-
-
-
-
-

Deduction guide

-
-
-
template<class Class>
-virtual_ptr(Class&) -> virtual_ptr<Class, BOOST_OPENMETHOD_DEFAULT_REGISTRY>;
-
-
-
-
-
-

Non-members

-
-
virtual_shared_ptr
-
-
-
template<class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_REGISTRY>
-using virtual_shared_ptr = virtual_ptr<std::shared_ptr<Class>, Policy>;
-
-
-
-

Convenience alias for virtual_ptr<std::shared_ptr<Class>, Policy>.

-
-
-
-
virtual_unique_ptr
-
-
-
template<class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_REGISTRY>
-using virtual_unique_ptr = virtual_ptr<std::unique_ptr<Class>, Policy>;
-
-
-
-

Convenience alias for virtual_ptr<std::unique_ptr<Class>, Policy>.

-
-
-
-
final_virtual_ptr
-
-
-
template<class Policy, class Class>
-inline auto final_virtual_ptr(Class&& obj);
-
-template<class Class>
-inline auto final_virtual_ptr(Class&& obj);
-
-
-
-

Utility functions, forwarding to virtual_ptr<Class, Policy>::final.

-
-
-

If Policy is not specified, BOOST_OPENMETHOD_DEFAULT_REGISTRY is used.

-
-
-
-
make_shared_virtual
-
-
-
template<
-    class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_REGISTRY, typename... T>
-inline auto make_shared_virtual(T&&... args)
-    -> shared_virtual_ptr<Class, Policy>;
-
-
-
-

Creates an object using std::make_shared and returns a virtual_shared_ptr to -it. The v-table pointer is initialized from the the Policy::static_vptr for -the class, which needs not be polymorphic.

-
-
-
-
make_unique_virtual
-
-
-
template<
-    class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_REGISTRY, typename... T>
-inline auto make_unique_virtual(T&&... args)
-    -> unique_virtual_ptr<Class, Policy>;
-
-
-
-

Creates an object using std::make_unique and returns a virtual_unique_ptr to -it. The v-table pointer is initialized from the the Policy::static_vptr for -the class, which needs not be polymorphic.

-
-
-
-
operator==
-
-
-
template<class Left, class Right, class Policy>
-auto operator==(
-    const virtual_ptr<Left, Policy>& left,
-    const virtual_ptr<Right, Policy>& right) -> bool;
-
-
-
-

Compares two virtual_ptr objects for equality.

-
-
-
-
operator!=
-
-
-
template<class Left, class Right, class Policy>
-auto operator!=(
-    const virtual_ptr<Left, Policy>& left,
-    const virtual_ptr<Right, Policy>& right) -> bool;
-
-
-
-

Compares two virtual_ptr objects for inequality.

-
-
-
-
-
-

virtual_traits

-
-

Synopsis

-
-

Defined in <boost/openmethod/core.hpp>.

-
-
-
-
namespace boost::openmethod {
-
-template<class, class>
-struct virtual_traits; // not defined
-
-template<class Class, class Policy>
-struct virtual_traits<..., Policy> {
-    using virtual_type = ...;
-    static auto peek(const T& arg) -> const ...&;
-    template<typename Derived> static auto cast(T& obj) -> ...;
-    template<class Other> using rebind = ...; // for smart virtual pointers
-};
-
-}
-
-
-
-
-

Description

-
-

Specializations of virtual_traits provide an interface for method and -virtual_ptr to manipulate virtual arguments.

-
-
-
-

Specializations

-
-

Specializations are provided for:

-
-
-
    -
  • -

    virtual_ptr<T, Policy>

    -
  • -
  • -

    const virtual_ptr<T, Policy>&

    -
  • -
  • -

    T&

    -
  • -
  • -

    T&&

    -
  • -
  • -

    T*

    -
  • -
  • -

    std::shared_ptr<T>: defined in <boost/openmethod/interop/std_shared_ptr.hpp>

    -
  • -
  • -

    const std::shared_ptr<T>&: defined in <boost/openmethod/interop/std_shared_ptr.hpp>

    -
  • -
  • -

    std::unique_ptr<T>: defined in <boost/openmethod/interop/std_unique_ptr.hpp>

    -
  • -
-
-
-
-

Members

-
-
virtual_type
-
-
-
using virtual_type = ...;
-
-
-
-

The class used for method selection. It must be registered in Policy.

-
-
-

For example, virtual_type in the following specializations are all Class:

-
-
-
    -
  • -

    virtual_traits<virtual_ptr<Class, Policy>>

    -
  • -
  • -

    virtual_traits<const virtual_ptr<std::shared_ptr<Class>&, Policy>

    -
  • -
  • -

    virtual_traits<Class&, Policy>

    -
  • -
  • -

    virtual_traits<const std::shared_ptr<Class>&, Policy>

    -
  • -
-
-
-
-
peek
-
-
-
static auto peek(T arg) -> const ...&;
-
-
-
-

Returns a value for the purpose of obtaining a v-table pointer for arg.

-
-
-

For example, peek returns a const T& for a T&, a const T&, a T&&, and -a std::shared_ptr<T>; and a const virtual_ptr<Class, Policy>& for a -const virtual_ptr<Class, Policy>&.

-
-
-
-
cast
-
-
-
template<typename Derived>
-static decltype(auto) cast(T& obj);
-
-
-
-

Casts argument obj to the type expected by an overrider.

-
-
-

For example, if a method takes a virtual_<Animal&>, an overrider for Cat& -uses virtual_traits to cast a Animal& to a Cat&.

-
-
-
-
rebind
-
-
-
template<class Other> using rebind = ...;
-
-
-
-

For smart pointers only. Rebinds the smart pointer to a different type. For -example, virtual_traits<std::shared_ptr<T>, Policy>::rebind<U> is -std::shared_ptr<U>.

-
-
-
-
-
-

use_classes

-
-

Synopsis

-
-

Defined in <boost/openmethod/core.hpp>.

-
-
-
-
namespace boost::openmethod {
-
-template<class... Classes, class Policy = BOOST_OPENMETHOD_DEFAULT_REGISTRY>
-struct use_classes {
-    use_classes();
-    ~use_classes();
-};
-
-}
-
-
-
-

Usage:

-
-
-
-
use_classes<Classes...> some_unique_name; // at file scope
-
-
-
-
-

Description

-
-

use_classes, instantiated as a static object, registers Classes in Policy.

-
-
-

Classes potentially involved in a method definition, an overrider, or a method -call must be registered via use_classes. A class may be registered multiple -times. A class and its direct bases must be listed together in one or more -instantiations of use_classes.

-
-
-

Virtual and multiple inheritance are supported, as long as they don’t result in -a class lattice that contains repeated inheritance.

-
-
- - - - - -
-
Note
-
-The default value for Policy is the value of -BOOST_OPENMETHOD_DEFAULT_REGISTRY when <boost/openmethod/core.hpp> is -included. Subsequently changing it has no retroactive effect. -
-
-
-
-

Members

-
-
constructor
-
-
-
use_classes();
-
-
-
-

Registers Classes and their inheritance relationships in Policy.

-
-
-
-
destructor
-
-
-
~use_classes();
-
-
-
-

Removes Classes and their inheritance relationships from Policy.

-
-
-
-
-
-

virtual_

-
-

Synopsis

-
-

Defined in <boost/openmethod/core.hpp>.

-
-
-
-
namespace boost::openmethod {
-
-template<typename T>
-struct virtual_;
-
-}
-
-
-
-
-

Description

-
-

Marks a formal parameter of a method as virtual. Requires a specialization of -virtual_traits for T and the Policy of the method. Specializations for -T&, T&&, T*, std::unique_ptr<T>, std::shared_ptr<T> and const -std::shared_ptr<T>& are provided. See the documentation of virtual_traits for -more information.

-
-
-
-
-

inplace_vptr

-
-

Synopsis

-
-

Defined in <boost/openmethod/inplace_vptr.hpp>.

-
-
-
-
namespace boost::openmethod {
-
-template<class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_REGISTRY>
-class inplace_vptr {
-  protected:
-    inplace_vptr();
-    ~inplace_vptr();
-    friend auto boost_openmethod_vptr(const Class& obj) -> vptr_type;
-};
-
-template<class Class, class Base, class... MoreBases>
-class inplace_vptr {
-  protected:
-    inplace_vptr();
-    ~inplace_vptr();
-    friend auto boost_openmethod_vptr(const Class& obj) -> vptr_type;
-        // if sizeof(MoreBases...) > 0
-};
-
-} // namespace boost::openmethod
-
-
-
-
-

Description

-
-

inplace_vptr is a CRTP class template that embeds and manages a vptr across a -class hierarchy.

-
-
-

If Class has no Bases, inplace_vptr adds a boost_openmethod_vptr private -member to Class. In either case, it sets the vptr to the v-table of Class -from Policy. It also creates a boost_openmethod_vptr friend function that -takes a a const Class& and returns the embedded vptr.

-
-
-

If Class has has more than one base, the boost_openmethod_vptr friend -function is also created. It returns one of the embedded vptrs (it doesn’t -matter which one, as they all have the same value). This is to resolve -ambiguities

-
-
-

As part of its implementation, inplace_vptr may also declare one or two free -functions (boost_openmethod_policy and boost_openmethod_bases) at certain -levels of the hierarchy.

-
-
-
-

Members

-
-
constructor
-
-
-
inplace_vptr();
-
-
-
-

Sets the vptr to the v-table for Class, obtained from Policy. If Policy -contains indirect_vptr, an additional level of indirection is added, thus -preserving the validity of the pointer across calls to initialize.

-
-
-
-
destructor
-
-
-
~inplace_vptr();
-
-
-
-

For each Base, sets the vptr to the v-table for that base.

-
-
-
-
Free Functions
-
-
-
auto boost_openmethod_vptr(const Class& obj) -> vptr_type;
-
-
-
-

Returns the vptr embedded in obj. -## abstract_policy

-
-
-
-
-

Synopsis

-
-

Defined in <boost/openmethod/policies/basic_policy.hpp>.

-
-
-
-
namespace boost::openmethod::policies {
-
-struct abstract_policy {};
-
-}
-
-
-
-
-

Description

-
-

abstract_policy is a required base class for a policy. It makes it possible -for metafunctions such as use_classes to discriminate between user classes -and the (optional) policy class.

-
-
-
-
-

domain

-
-

Synopsis

-
-

Defined in <boost/openmethod/policies/basic_policy.hpp>.

-
-
-
-
namespace boost::openmethod::policies {
-
-template<class Policy>
-struct domain {
-    template<class Class> static vptr_type static_vptr;
-    // unspecified members
-};
-
-}
-
-
-
-
-

Description

-
-

domain is a registry of classes and methods registered in a Policy, -and their dispatch tables.

-
-
-
-

Members

-
-
static_vptr
-
-
-
template<class Class>
-static vptr_type static_vptr;
-
-
-
-

Contains the pointer to the v-table for Class. Set by initialize.

-
-
-
-
-
-

basic_policy

-
-

Synopsis

-
-
-
namespace boost::openmethod {
-
-namespace policies {
-
-template<class Policy, class... Facets>
-struct basic_policy : abstract_policy, domain<Policy>, Facets... {
-    template<class Facet>
-    static constexpr bool has = /*unspecified*/;
-
-    template<class NewPolicy>
-    using fork = /*unspecified*/;
-
-    template<class... Facets>
-    using with = /*unspecified*/;
-
-    template<class... Facets>
-    using without = /*unspecified*/;
-};
-
-struct release : basic_policy<release, ...> {};
-
-struct debug : release::add<...> {};
-
-} // policies
-
-#ifdef NDEBUG
-using default_registry = policies::release;
-#else
-using default_registry = policies::debug;
-#endif
-
-} // boost::openmethod
-
-
-
-
-

Headers

-
-

Defined in <boost/openmethod/policies/basic_policy.hpp>. Also available via -<boost/openmethod/core.hpp> and <boost/openmethod.hpp>.

-
-
-
-

Description

-
-

basic_policy implements a policy, which consists of a a collection of methods, -classes, dispatch data, and policys, which specify how to obtain a pointer to a -v-table from an object, how to report errors, whether to perform runtime sanity -checks, etc.

-
-
-

basic_policy has state. It uses the Curiously Recurring Template Pattern to -allow distinct policies to have distinct sets of static variables.

-
-
-
-

Members

-
-
has
-
-
-
template<class Facet>
-static constexpr bool has;
-
-
-
-

Evaluates to true if Policy contains Facet.

-
-
-
-
fork
-
-
-
template<class NewPolicy>
-using fork;
-
-
-
-

Creates a new policy from an existing one. NewPolicy does not share static -variables with the original Policy. The new policy does not retain any -knowledge of the classes and methods registered in the original.

-
-
-

fork forks the policys in the policy as well: any policy instantiated from a -class template is assumed to take a policy as its first template argument. The -template is re-instantiated with the new policy as the first arguments, while -the other arguments remain the same.

-
-
-
-
with
-
-
-
template<class... Facets>
-using with;
-
-
-
-
-
Requires
-
-

Facets is a list of classes that derive from policy.

-
-
Returns
-
-

A new policy containing Facets, and the policys from the original -that do not have the same category as Facets.

-
-
Examples
-
-
-
    -
  • -

    struct dyn_load : default_registry::fork<dyn_load>::with<indirect_vptr> {};
    -Creates a policy just like default_registry, with an extra indirection added -to the v-table pointers. This policy is suitable for use with dynamic loading.

    -
  • -
  • -

    struct release_with_diags : release::fork<release_with_diags>::with<basic_error_output<release_with_diags>> {};
    -Creates a policy just like release, except that it prints a diagnostic -message before terminating with abort().

    -
  • -
  • -

    struct default_throw : default_registry::fork<default_throw>::with<throw_error_handler> {};
    -Creates a policy just like default_registry, except that it reports errors by -throwing exceptions, instead of calling a std::function like the default -error handler does.

    -
  • -
-
-
-
-
-
-
-
without
-
-
-
template<class... Facets>
-using without;
-
-
-
-
-
Requires
-
-

Facets is a list of policy categories.

-
-
Returns
-
-

A new policy containing the policys from the original that do not have -the same category as Facets.

-
-
Examples
-
-
-
    -
  • -

    struct use_map : default_registry::fork<use_map>::with<vptr_map<use_map>>::without<type_hash> {};
    -Creates a policy just like default_registry, except that it stores pointers to -v-table in a std::unordered_map. Also removes the hash function, since it -will not be used.

    -
  • -
-
-
-
-
-
-
-
-

Non-members

-
-
release
-
-
-
struct release;
-
-
-
-

A policy that contains policys std_rtti, fast_perfect_hash, vptr_vector and -default_error_handler.

-
-
-
-
debug
-
-
-
struct debug;
-
-
-
-

The release policy with additional policy implementations runtime_checks, -basic_error_output and basic_trace_output.

-
-
- - - - - -
-
Note
-
-debug extends release but it does not a fork it. Both policies use the -same domain. -
-
-
-
-
default_registry
-
-

An alias for release if NDEBUG is defined, and for debug otherwise.

-
-
-
-
-
-

policy

-
-

Synopsis

-
-

Defined in <boost/openmethod/policies/basic_policy.hpp>.

-
-
-
-
namespace boost::openmethod::policies {
-
-struct policy {
-    static auto finalize() -> void;
-};
-
-} // boost::openmethod::policies
-
-
-
-
-

Description

-
-

policy is the base class of all policys. It provides an empty finalize static -function which can be overriden (via shadowing) by derived classes.

-
-
-
-

Members

-
-
finalize
-
-
-
static auto finalize() -> void;
-
-
-
-

Does nothing.

-
-
-
-
-
-

rtti

-
-

Synopsis

-
-

Defined in <boost/openmethod/policies/basic_policy.hpp>.

-
-
-
-
namespace boost::openmethod::policies {
-
-struct rtti : policy {};
-
-} // boost::openmethod::policies
-
-
-
-
-

Description

-
-

The rtti policy provides type information for classes and objects, implements -downcast in presence of virtual inheritance, and writes descriptions of types to -an ostream-like object.

-
-
-
-

Requirements

-
-
is_polymorphic
-
-
-
template<class Class>
-static constexpr bool is_polymorphic;
-
-
-
-

true if Class is polymorphic.

-
-
-
-
static_type
-
-
-
template<class Class>
-static auto static_type() -> type_id;
-
-
-
-

Returns a type_id for Class.

-
-
-
-
dynamic_type
-
-
-
template<class Class>
-static auto dynamic_type(const Class& obj) -> type_id;
-
-
-
-

Returns a type_id for an object’s dynamic type.

-
-
-
-
type_name
-
-
-
template<typename Stream>
-static auto type_name(type_id type, Stream& stream) -> void;
-
-
-
-

Writes a description of type to stream.

-
-
-

This requirement is optional. rtti provides a default implementation that writes typeid({type}) to stream.

-
-
-
-
type_index
-
-
-
static auto type_index(type_id type) -> /* unspecified */;
-
-
-
-

Returns a unique key for type. Required only for RTTI systems that assign more -than one type "identifiers" to a type. For example, standard RTTI allows -implementations to have multiple instances of std::type_info for the same -type.

-
-
-
-
dynamic_cast_ref
-
-
-
template<typename D, typename B>
-static auto dynamic_cast_ref(B&& obj) -> D;
-
-
-
-

Casts obj to D. Required only if using virtual inheritance.

-
-
-
-
-
-

std_rtti

-
-

Synopsis

-
-

Defined in <boost/openmethod/policies/std_rtti.hpp>.

-
-
-
-
namespace boost::openmethod::policies {
-
-struct std_rtti : rtti {
-    template<class Class>
-    static auto static_type() -> type_id;
-
-    template<class Class>
-    static auto dynamic_type(const Class& obj) -> type_id;
-
-    template<typename Stream>
-    static auto type_name(type_id type, Stream& stream) -> void;
-
-    static auto type_index(type_id type) -> std::type_index;
-
-    template<typename D, typename B>
-    static auto dynamic_cast_ref(B&& obj) -> D;
-};
-
-} // boost::openmethod::policies
-
-
-
-
-

Description

-
-

std_rtti is an implementation of the rtti policy that uses standard RTTI.

-
-
-
-

Members

-
-
static_type
-
-
-
template<class Class>
-static auto static_type() -> type_id;
-
-
-
-

Return the address of Class’s `type_info, cast to a type_id.

-
-
-
-
dynamic_type
-
-
-
template<class Class>
-static auto dynamic_type(const Class& obj) -> type_id;
-
-
-
-

Return the address of obj's type_info, cast to a type_id.

-
-
-
-
type_name
-
-
-
template<typename Stream>
-static auto type_name(type_id type, Stream& stream) -> void;
-
-
-
-

Write the demangled name of the class identified by type to stream. -Execute stream << reinterpret_cast<const std::type_info*>(type)→name().

-
-
-
-
type_index
-
-
-
static auto type_index(type_id type) -> /*unspecified*/;
-
-
-
-

Return std::type_index(reinterpret_cast<const std::type_info>(type)).

-
-
-

The function is required because C++ does not guarantee that there is a single -instance of std::type_info for each specific type.

-
-
-
-
dynamic_cast_ref
-
-
-
template<typename Derived, typename Base>
-static auto dynamic_cast_ref(Base&& obj) -> Derived;
-
-
-
-

Cast obj using the dynamic_cast operator.

-
-
-
-
-
-

deferred_static_rtti

-
-

Synopsis

-
-

Defined in <boost/openmethod/policies/basic_policy.hpp>.

-
-
-
-
namespace boost::openmethod::policies {
-
-struct deferred_static_rtti : rtti {};
-
-}
-
-
-
-
-

Description

-
-

deferred_static_rtti is a policy that defers collection of static type ids.

-
-
-

Some custom RTTI systems rely on static constructors to assign type ids. -OpenMethod itself relies on static constructors to register classes, methods and -overriders, calling the static_type function from the rtti policy in the -process. This can result in collecting the type ids before they have been -initialized. Adding this policy to a policy moves the collection of type ids to -initialize.

-
-
-
-
-

minimal_rtti

-
-

Synopsis

-
-
-
struct minimal_rtti : rtti {
-    template<class Class>
-    static constexpr bool is_polymorphic = false;
-
-    template<typename Class>
-    static auto static_type() -> type_id;
-};
-
-
-
-
-

Description

-
-

minimal_rtti is an implementation of the rtti policy that only uses static -type information.

-
-
-

minimal_rtti provides the only function strictly required for the rtti -policy.

-
-
-

This policy can be used in programs that call methods solely via -virtual_ptrs created with the "final" constructs. Virtual inheritance -is not supported. Classes are not required to be polymorphic.

-
-
-
-

Members

-
-
is_polymorphic
-
-
-
template<class Class>
-static constexpr bool is_polymorphic = false;
-
-
-
-

This policy does not support polymorphic classes.

-
-
-
-
static_type
-
-
-
template<class Class>
-static auto static_type() -> type_id;
-
-
-
-

Returns the address of a local static char variable, cast to type_id.

-
-
-
-
-
-

extern_vptr

-
-

Synopsis

-
-

Defined in <boost/openmethod/policies/basic_policy.hpp>.

-
-
-
-
namespace boost::openmethod::policies {
-
-struct extern_vptr : policy {};
-
-}
-
-
-
-
-

Description

-
-

extern_vptr is a policy that stores and returns pointers to v-tables for -registered classes.

-
-
-
-

Requirements

-
-
register_vptrs
-
-
-
template<typename ForwardIterator>
-auto register_vptrs(ForwardIterator first, ForwardIterator last) -> void;
-
-
-
-

ForwardIterator is a forward iterator over a range of objects that contain -information about the type ids and the vptr of a registered class. They have the -following member functions:

-
-
-
-
auto type_id_begin() const -> type_id_forward_iterator;
-auto type_id_end() const -> type_id_forward_iterator;
-auto vptr() const -> const vptr_type&;
-
-
-
-

type_id_begin and type_id_end return iterators delimiting a range of -`type_id`s for a class.

-
-
-

vptr returns a reference to a static variable containing a pointer to the -v-table for a the class. Its value is set by initialize. While the value of -the variable changes with each call to initialize, the variable itself remains -the same.

-
-
-
-
-
-

indirect_vptr

-
-

Synopsis

-
-
-
struct indirect_vptr : policy {};
-
-
-
-
-

Description

-
-

indirect_vptr is a policy that makes virtual_ptrs and inplace_vptr use -pointers to pointers to v-tables, instead of straight pointers. As a -consequence, they remain valid after a call to initialize.

-
-
-
-

Requirements

-
-

None. The policy is its own implementation.

-
-
-
-
-

vptr_vector

-
-

Synopsis

-
-

Defined in <boost/openmethod/policies/vptr_vector.hpp>.

-
-
-
-
namespace boost::openmethod::policies {
-
-template<class Policy>
-class vptr_vector : Base {
-  public:
-    template<typename ForwardIterator>
-    static auto register_vptrs(ForwardIterator first, ForwardIterator last) -> void;
-
-    template<class Class>
-    static auto dynamic_vptr(const Class& arg) -> const vptr_type&;
-};
-
-}
-
-
-
-
-

Description

-
-

vptr_vector is an implementation or external_vptr that keeps the pointers to -the v-tables in a std::vector. If Policy contains indirect_vptr, a level -of indirection is added, making the policy usable in presence of dynamic -loading.

-
-
-

Policy is the policy containing the policy.

-
-
-
-

Members

-
-
register_vptrs
-
-
-
template<typename ForwardIterator>
-auto register_vptrs(ForwardIterator first, ForwardIterator last) -> void;
-
-
-
-

Stores the pointers to v-tables in a vector, indexed by the (possibly hashed) -type_id`s of the classes registered in `Policy.

-
-
-

If Policy contains a type_hash policy, call its hash_initialize -function, and uses it to convert the type_ids to an index.

-
-
-
-
dynamic_vptr
-
-
-
template<class Class>
-auto dynamic_vptr(const Class& object) -> const vptr_type&;
-
-
-
-

Returns a pointer to the v-table for object (by reference).

-
-
-

Obtains a type_id for object using Policy::dynamic_type. If Policy -contains a type_hash policy, uses it to convert the result to an index; -otherwise, uses the type_id as the index.

-
-
-
-
-
-

vptr_map

-
-

Synopsis

-
-
-
namespace boost::openmethod::policies {
-
-### Synopsis
-
-template<class Policy, class MapAdaptor = mp11::mp_quote<std::unordered_map>>
-class vptr_map : public extern_vptr {
-  public:
-    template<typename ForwardIterator>
-    static auto register_vptrs(ForwardIterator first, ForwardIterator last) -> void;
-
-    template<class Class>
-    static auto dynamic_vptr(const Class& arg) -> const vptr_type&;
-};
-
-}
-
-
-
-
-

Description

-
-

vptr_map is an implementation of external_vptr that stores the pointers to -the v-tables in a map. If `Policy contains indirect_vptr, a level of -indirection is added, making the policy usable in presence of dynamic loading.

-
-
-

Policy is the policy containing the policy.

-
-
-

MapAdaptor is a Boost.Mp11 quoted metafunction that returns a map type.

-
-
-
-

Members

-
-
register_vptrs
-
-
-
template<typename ForwardIterator>
-auto register_vptrs(ForwardIterator first, ForwardIterator last) -> void;
-
-
-
-

Stores the pointers to v-tables in a Map.

-
-
-
-
dynamic_vptr
-
-
-
template<class Class>
-auto dynamic_vptr(const Class& object) -> const vptr_type&;
-
-
-
-

Returns a pointer to the v-table for object (by reference).

-
-
-

If Policy contains the runtime_checks policy, checks if Class is -registered. If it is not, and Policy contains a error_handler policy, calls -its error function; then calls abort.

-
-
-
-
-
-

type_hash

-
-

Synopsis

-
-

Defined in <boost/openmethod/policies/basic_policy.hpp>.

-
-
-
-
namespace boost::openmethod::policies {
-
-struct type_hash : policy {};
-
-} // boost::openmethod::policies
-
-
-
-
-

Description

-
-

type_hash is a policy that provides a hash function for a fixed set of -type_ids.

-
-
-
-

Requirements

- -
-
-

hash_type_id

-
-
-
static auto hash_type_id(type_id type) -> type_id;
-
-
-
-

Returns the hash of type.

-
-
-
hash_initialize
-
-
-
template<typename ForwardIterator>
-static auto hash_initialize(ForwardIterator first, ForwardIterator last)
-  -> Report;
-
-
-
-

Finds a hash function for the type_ids in the range [first, last). -ForwardIterator is the same as in vptr_vector::register_vptrs.

-
-
-

hash_initialize returns a Report object which is required to have two -members, first and last, which define the range [first, last) of the -possible output values of the hash function.

-
-
-
-
-
-

fast_perfect_hash

-
-

Synopsis

-
-

Defined in <boost/openmethod/policies/fast_perfect_hash.hpp>.

-
-
-
-
class fast_perfect_hash : type_hash
-{
-  public:
-    static auto hash_type_id(type_id type) -> type_id;
-    template<typename ForwardIterator>
-    static auto hash_initialize(ForwardIterator first, ForwardIterator last) -> Report;
-};
-
-
-
-
-

Description

-
-

fast_perfect_hash implements a very fast, perfect (but not minimal) hash -function for type_ids.

-
-
-
-

Members

-
-

Find two factors

-
-
-
hash_type_id
-
-
-
static auto hash_type_id(type_id type) -> type_id;
-
-
-
-

Returns (type * M) >> S, where M and S are factors found by -hash_initialize.

-
-
-

If the policy has a runtime_checks policy, hash_type_id checks that type -corresponds to a registered class. If not, it reports a unknown_class_error -using the policy’s error_handler policy, if present, then calls abort.

-
-
-
-
hash_initialize
-
-
-
template<typename ForwardIterator>
-auto hash_initialize(ForwardIterator first, ForwardIterator last) -> Report;
-
-
-
-

Finds factors M and S such that hash_type_id is a collision-free hash -function.

-
-
-

If no such factors cannot be found, hash_initialize reports a -hash_search_error using the policy’s error_handler policy, if present, the -calls abort.

-
-
-

If the policy has a trace policy, hash_initialize uses it to write a -summary of the search.

-
-
-
-
-
-

error_handler

-
-

Synopsis

-
-

Defined in <boost/openmethod/policies/basic_policy.hpp>.

-
-
-
-
namespace boost::openmethod {
-
-namespace policies {
-
-struct error_handler;
-
-}
-
-struct openmethod_error {};
-
-struct not_implemented_error : openmethod_error {
-    type_id method;
-    std::size_t arity;
-    static constexpr std::size_t max_types = 16;
-    type_id types[max_types];
-};
-
-struct unknown_class_error : openmethod_error {
-    type_id type;
-};
-
-struct hash_search_error : openmethod_error {
-    std::size_t attempts;
-    std::size_t buckets;
-};
-
-struct type_mismatch_error : openmethod_error {
-    type_id type;
-};
-
-}
-
-
-
-
-

Description

-
-

error_handler is a policy that handles errors.

-
-
-

When an error is encountered, either during initialize or method dispatch, the -program is terminated via a call to abort. If this policy is present in the -policy, its error function is called with an error object. It can prevent -termination by throwing an exception.

-
-
-
-

Requirements

-
-

Implementations of error_handler must provide the following functions:

-
-
-
error
-
-
-
static auto error(const T&) -> void;
-
-
-
-
-
-
-

default_error_handler

-
-

Synopsis

-
-

Defined in <boost/openmethod/policies/default_error_handler.hpp>.

-
-
-
-
namespace boost::openmethod::policies {
-
-template<class Policy>
-class default_error_handler : public error_handler {
-  public:
-    using error_variant = std::variant<
-        openmethod_error, not_implemented_error, unknown_class_error,
-        hash_search_error, type_mismatch_error, static_slot_error,
-        static_stride_error>;
-    using function_type = std::function<void(const error_variant& error)>;
-
-    template<class Error>
-    static auto error(const Error& error) -> void;
-    static auto set_error_handler(error_handler_type handler) -> function_type;
-};
-
-}
-
-
-
-
-

Description

-
-

default_error_handler is an implementation of error_handler that calls a -std::function to handle the error.

-
-
-
-

Members

-
-
error
-
-
-
template<class Error>
-static auto error(const Error& error) -> void;
-
-
-
-

Calls the function last set via set_error_handler or, if it was never called, -and if Policy contains an output policy, use it to print a description -of error.

-
-
-
-
error
-
-
-
static auto set_error_handler(function_type handler) -> function_type;
-
-
-
-

Sets handler as the function to call in case of error.

-
-
-
-
-
-

throw_error_handler

-
-

Synopsis

-
-

Defined in <boost/openmethod/policies/throw_error_handler.hpp>.

-
-
-
-
namespace boost::openmethod::policies {
-
-struct throw_error_handler : error_handler {
-    template<class Error>
-    [[noreturn]] static auto error(const Error& error) -> void;
-};
-
-} // boost::openmethod::policies
-
-
-
-
-

Description

-
-

throw_error_handler is an implementation of the error_handler policy that -throws the error as an exception.

-
-
-
-

Members

-
-
error
-
-
-
template<class Error>
-[[noreturn]] static auto error(const Error& error) -> void;
-
-
-
-

Throws error.

-
-
-
-
-
-

basic_error_output

-
-

Synopsis

-
-

Defined in <boost/openmethod/policies/basic_error_output.hpp>.

-
-
-
-
namespace boost::openmethod::policies {
-
-template<class Policy, typename Stream = /*unspecified*/>
-struct basic_error_output : output {
-    static Stream error_stream;
-};
-
-}
-
-
-
-
-

Description

-
-

basic_error_output is an implementation of output that writes error -messages to a LightweightOutputStream.

-
-
-
-

Members

-
-
error_stream
-
-
-
Stream  error_stream;
-
-
-
-

Initialized by the default constructor of Stream. It is the responsibility of -the program to initializate it if needed, e.g., for a std::ofstream, to open -it.

-
-
-
-
-
-

basic_trace_output

-
-

Synopsis

-
-

Defined in <boost/openmethod/policies/basic_trace_output.hpp>.

-
-
-
-
namespace boost::openmethod::policies {
-
-template<class Policy, typename Stream = /*unspecified*/>
-struct basic_trace_output : trace {
-    static bool trace_enabled;
-    static Stream trace_stream;
-};
-
-}
-
-
-
-
-

Description

-
-

basic_error_output is an implementation of trace that writes error -messages to a LightweightOutputStream.

-
-
-
-

Members

-
-
trace_enabled
-
-
-
static bool trace_enabled;
-
-
-
-

Set to true if environment variable BOOST_OPENMETHOD_TRACE is set to 1.

-
-
-
-
trace_stream
-
-
-
static Stream trace_stream;
-
-
-
-

Initialized by the default constructor of Stream. It is the responsibility of -the program to prepare it for output if needed, e.g., for a std::ofstream, to -open it.

-
-
-
-
-
-

LightweightOutputStream

-
-

Description

-
-

LightweightOutputStream is a concept describing a std::ostream-like class with -a reduced set of operations.

-
-
-

While convenient, std::ostream and its implementations constitute a sizeable -piece of code, which may make it unsuitable for certain applications. OpenMethod -uses a small subset of the operations supported by std::ostream. By default, -the library uses a lightweight implementation based on the C stream functions.

-
-
-

Implementations of LightweightOutputStream provide the following functions:

-
- ---- - - - - - - - - - - - - - - - - - - - - - - - - -
NameDescription
-

LightweightOutputStream& operator<<(LightweightOutputStream& os, const char* str)

-
-

Write a null-terminated string str to os

-
-

LightweightOutputStream& operator<<(LightweightOutputStream& os, const std::string_view& view)

-
-

Write a view to `os

-
-

LightweightOutputStream& operator<<(LightweightOutputStream& os, const void* value)

-
-

Write a representation of a pointer to os

-
-

LightweightOutputStream& operator<<(LightweightOutputStream& os, std::size_t value)

-
-

Write an unsigned integer to os

-
-
-
-
-
-
- - - diff --git a/doc/html/rouge-github.css b/doc/html/rouge-github.css deleted file mode 100644 index b126f17f..00000000 --- a/doc/html/rouge-github.css +++ /dev/null @@ -1,199 +0,0 @@ -.highlight table td { padding: 5px; } -.highlight table pre { margin: 0; } -.highlight .cm { - color: #999988; - font-style: italic; -} -.highlight .cp { - color: #999999; - font-weight: bold; -} -.highlight .c1 { - color: #999988; - font-style: italic; -} -.highlight .cs { - color: #999999; - font-weight: bold; - font-style: italic; -} -.highlight .c, .highlight .cd { - color: #999988; - font-style: italic; -} -.highlight .err { -} -.highlight .gd { - color: #000000; - background-color: #ffdddd; -} -.highlight .ge { - color: #000000; - font-style: italic; -} -.highlight .gr { - color: #aa0000; -} -.highlight .gh { - color: #999999; -} -.highlight .gi { - color: #000000; - background-color: #ddffdd; -} -.highlight .go { - color: #888888; -} -.highlight .gp { - color: #555555; -} -.highlight .gs { - font-weight: bold; -} -.highlight .gu { - color: #aaaaaa; -} -.highlight .gt { - color: #aa0000; -} -.highlight .kc { - font-weight: bold; -} -.highlight .kd { - font-weight: bold; -} -.highlight .kn { - font-weight: bold; -} -.highlight .kp { - font-weight: bold; -} -.highlight .kr { - font-weight: bold; -} -.highlight .kt { - color: #445588; - font-weight: bold; -} -.highlight .k, .highlight .kv { - font-weight: bold; -} -.highlight .mf { - color: #009999; -} -.highlight .mh { - color: #009999; -} -.highlight .il { - color: #009999; -} -.highlight .mi { - color: #009999; -} -.highlight .mo { - color: #009999; -} -.highlight .m, .highlight .mb, .highlight .mx { - color: #009999; -} -.highlight .sb { - color: #d14; -} -.highlight .sc { - color: #d14; -} -.highlight .sd { - color: #d14; -} -.highlight .s2 { - color: #d14; -} -.highlight .se { - color: #d14; -} -.highlight .sh { - color: #d14; -} -.highlight .si { - color: #d14; -} -.highlight .sx { - color: #d14; -} -.highlight .sr { - color: #009926; -} -.highlight .s1 { - color: #d14; -} -.highlight .ss { - color: #990073; -} -.highlight .s { - color: #d14; -} -.highlight .na { - color: #008080; -} -.highlight .bp { - color: #999999; -} -.highlight .nb { - color: #0086B3; -} -.highlight .nc { - color: #445588; - font-weight: bold; -} -.highlight .no { - color: #008080; -} -.highlight .nd { - color: #3c5d5d; - font-weight: bold; -} -.highlight .ni { - color: #800080; -} -.highlight .ne { - color: #990000; - font-weight: bold; -} -.highlight .nf { - color: #990000; - font-weight: bold; -} -.highlight .nl { - color: #990000; - font-weight: bold; -} -.highlight .nn { - color: #555555; -} -.highlight .nt { - color: #000080; -} -.highlight .vc { - color: #008080; -} -.highlight .vg { - color: #008080; -} -.highlight .vi { - color: #008080; -} -.highlight .nv { - color: #008080; -} -.highlight .ow { - font-weight: bold; -} -.highlight .o { - font-weight: bold; -} -.highlight .o { - font-weight: bold; -} -.highlight .w { - color: #bbbbbb; -} diff --git a/doc/html/skin.png b/doc/html/skin.png deleted file mode 100644 index 23540cc3..00000000 Binary files a/doc/html/skin.png and /dev/null differ diff --git a/doc/html/zajo-dark.css b/doc/html/zajo-dark.css deleted file mode 100644 index 4247e85e..00000000 --- a/doc/html/zajo-dark.css +++ /dev/null @@ -1,478 +0,0 @@ -/* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */ -/* Uncomment @import statement below to use as custom stylesheet */ -/*@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700";*/ - -/* Zajo's custom font import. The rest of the customizations are at the bottom of this css file, which is otherwise kept unchanged */ -@import "https://fonts.googleapis.com/css?family=Anonymous+Pro|Istok+Web|Quicksand|Poiret+One"; - -article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block} -audio,canvas,video{display:inline-block} -audio:not([controls]){display:none;height:0} -script{display:none!important} -html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%} -a{background:transparent} -a:focus{outline:thin dotted} -a:active,a:hover{outline:0} -h1{font-size:2em;margin:.67em 0} -abbr[title]{border-bottom:1px dotted} -b,strong{font-weight:bold} -dfn{font-style:italic} -hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0} -mark{background:#ff0;color:#000} -code,kbd,pre,samp{font-family:monospace;font-size:1em} -pre{white-space:pre-wrap} -q{quotes:"\201C" "\201D" "\2018" "\2019"} -small{font-size:80%} -sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline} -sup{top:-.5em} -sub{bottom:-.25em} -img{border:0} -svg:not(:root){overflow:hidden} -figure{margin:0} -fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em} -legend{border:0;padding:0} -button,input,select,textarea{font-family:inherit;font-size:100%;margin:0} -button,input{line-height:normal} -button,select{text-transform:none} -button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer} -button[disabled],html input[disabled]{cursor:default} -input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0} -button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0} -textarea{overflow:auto;vertical-align:top} -table{border-collapse:collapse;border-spacing:0} -*,*::before,*::after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box} -html,body{font-size:100%} -body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto;tab-size:4;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased} -a:hover{cursor:pointer} -img,object,embed{max-width:100%;height:auto} -object,embed{height:100%} -img{-ms-interpolation-mode:bicubic} -.left{float:left!important} -.right{float:right!important} -.text-left{text-align:left!important} -.text-right{text-align:right!important} -.text-center{text-align:center!important} -.text-justify{text-align:justify!important} -.hide{display:none} -img,object,svg{display:inline-block;vertical-align:middle} -textarea{height:auto;min-height:50px} -select{width:100%} -.center{margin-left:auto;margin-right:auto} -.stretch{width:100%} -.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em} -div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr} -a{color:#2156a5;text-decoration:underline;line-height:inherit} -a:hover,a:focus{color:#1d4b8f} -a img{border:none} -p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility} -p aside{font-size:.875em;line-height:1.35;font-style:italic} -h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em} -h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0} -h1{font-size:2.125em} -h2{font-size:1.6875em} -h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em} -h4,h5{font-size:1.125em} -h6{font-size:1em} -hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0} -em,i{font-style:italic;line-height:inherit} -strong,b{font-weight:bold;line-height:inherit} -small{font-size:60%;line-height:inherit} -code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)} -ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit} -ul,ol{margin-left:1.5em} -ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em} -ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit} -ul.square{list-style-type:square} -ul.circle{list-style-type:circle} -ul.disc{list-style-type:disc} -ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0} -dl dt{margin-bottom:.3125em;font-weight:bold} -dl dd{margin-bottom:1.25em} -abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help} -abbr{text-transform:none} -blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd} -blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)} -blockquote cite::before{content:"\2014 \0020"} -blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)} -blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)} -@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2} -h1{font-size:2.75em} -h2{font-size:2.3125em} -h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em} -h4{font-size:1.4375em}} -table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede} -table thead,table tfoot{background:#f7f8f7} -table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left} -table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)} -table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7} -table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6} -h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em} -h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400} -.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table} -.clearfix::after,.float-group::after{clear:both} -*:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed;word-wrap:break-word} -*:not(pre)>code.nobreak{word-wrap:normal} -*:not(pre)>code.nowrap{white-space:nowrap} -pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeSpeed} -em em{font-style:normal} -strong strong{font-weight:400} -.keyseq{color:rgba(51,51,51,.8)} -kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap} -.keyseq kbd:first-child{margin-left:0} -.keyseq kbd:last-child{margin-right:0} -.menuseq,.menuref{color:#000} -.menuseq b:not(.caret),.menuref{font-weight:inherit} -.menuseq{word-spacing:-.02em} -.menuseq b.caret{font-size:1.25em;line-height:.8} -.menuseq i.caret{font-weight:bold;text-align:center;width:.45em} -b.button::before,b.button::after{position:relative;top:-1px;font-weight:400} -b.button::before{content:"[";padding:0 3px 0 2px} -b.button::after{content:"]";padding:0 2px 0 3px} -p a>code:hover{color:rgba(0,0,0,.9)} -#header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em} -#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table} -#header::after,#content::after,#footnotes::after,#footer::after{clear:both} -#content{margin-top:1.25em} -#content::before{content:none} -#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0} -#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf} -#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px} -#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap} -#header .details span:first-child{margin-left:-.125em} -#header .details span.email a{color:rgba(0,0,0,.85)} -#header .details br{display:none} -#header .details br+span::before{content:"\00a0\2013\00a0"} -#header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)} -#header .details br+span#revremark::before{content:"\00a0|\00a0"} -#header #revnumber{text-transform:capitalize} -#header #revnumber::after{content:"\00a0"} -#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem} -#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em} -#toc>ul{margin-left:.125em} -#toc ul.sectlevel0>li>a{font-style:italic} -#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0} -#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none} -#toc li{line-height:1.3334;margin-top:.3334em} -#toc a{text-decoration:none} -#toc a:active{text-decoration:underline} -#toctitle{color:#7a2518;font-size:1.2em} -@media screen and (min-width:768px){#toctitle{font-size:1.375em} -body.toc2{padding-left:15em;padding-right:0} -#toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto} -#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em} -#toc.toc2>ul{font-size:.9em;margin-bottom:0} -#toc.toc2 ul ul{margin-left:0;padding-left:1em} -#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em} -body.toc2.toc-right{padding-left:0;padding-right:15em} -body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}} -@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0} -#toc.toc2{width:20em} -#toc.toc2 #toctitle{font-size:1.375em} -#toc.toc2>ul{font-size:.95em} -#toc.toc2 ul ul{padding-left:1.25em} -body.toc2.toc-right{padding-left:0;padding-right:20em}} -#content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px} -#content #toc>:first-child{margin-top:0} -#content #toc>:last-child{margin-bottom:0} -#footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em} -#footer-text{color:rgba(255,255,255,.8);line-height:1.44} -#content{margin-bottom:.625em} -.sect1{padding-bottom:.625em} -@media screen and (min-width:768px){#content{margin-bottom:1.25em} -.sect1{padding-bottom:1.25em}} -.sect1:last-child{padding-bottom:0} -.sect1+.sect1{border-top:1px solid #e7e7e9} -#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400} -#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em} -#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible} -#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none} -#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221} -.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em} -.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic} -table.tableblock.fit-content>caption.title{white-space:nowrap;width:0} -.paragraph.lead>p,#preamble>.sectionbody>[class="paragraph"]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)} -table.tableblock #preamble>.sectionbody>[class="paragraph"]:first-of-type p{font-size:inherit} -.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%} -.admonitionblock>table td.icon{text-align:center;width:80px} -.admonitionblock>table td.icon img{max-width:none} -.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase} -.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6)} -.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0} -.exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px} -.exampleblock>.content>:first-child{margin-top:0} -.exampleblock>.content>:last-child{margin-bottom:0} -.sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px} -.sidebarblock>:first-child{margin-top:0} -.sidebarblock>:last-child{margin-bottom:0} -.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center} -.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0} -.literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8} -.sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class="highlight"],.sidebarblock .listingblock pre[class^="highlight "],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1} -.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;overflow-x:auto;padding:1em;font-size:.8125em} -@media screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}} -@media screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}} -.literalblock pre.nowrap,.literalblock pre.nowrap pre,.listingblock pre.nowrap,.listingblock pre.nowrap pre{white-space:pre;word-wrap:normal} -.literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)} -.listingblock pre.highlightjs{padding:0} -.listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px} -.listingblock pre.prettyprint{border-width:0} -.listingblock>.content{position:relative} -.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999} -.listingblock:hover code[data-lang]::before{display:block} -.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:#999} -.listingblock.terminal pre .command:not([data-prompt])::before{content:"$"} -table.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none} -table.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45} -table.pyhltable td.code{padding-left:.75em;padding-right:0} -pre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #dddddf} -pre.pygments .lineno{display:inline-block;margin-right:.25em} -table.pyhltable .linenodiv{background:none!important;padding-right:0!important} -.quoteblock{margin:0 1em 1.25em 1.5em;display:table} -.quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em} -.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify} -.quoteblock blockquote{margin:0;padding:0;border:0} -.quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)} -.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0} -.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right} -.verseblock{margin:0 1em 1.25em} -.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility} -.verseblock pre strong{font-weight:400} -.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex} -.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic} -.quoteblock .attribution br,.verseblock .attribution br{display:none} -.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)} -.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none} -.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0} -.quoteblock.abstract{margin:0 1em 1.25em;display:block} -.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center} -.quoteblock.excerpt,.quoteblock .quoteblock{margin:0 0 1.25em;padding:0 0 .25em 1em;border-left:.25em solid #dddddf} -.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem} -.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;text-align:left;margin-right:0} -table.tableblock{max-width:100%;border-collapse:separate} -p.tableblock:last-child{margin-bottom:0} -td.tableblock>.content{margin-bottom:-1.25em} -table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede} -table.grid-all>thead>tr>.tableblock,table.grid-all>tbody>tr>.tableblock{border-width:0 1px 1px 0} -table.grid-all>tfoot>tr>.tableblock{border-width:1px 1px 0 0} -table.grid-cols>*>tr>.tableblock{border-width:0 1px 0 0} -table.grid-rows>thead>tr>.tableblock,table.grid-rows>tbody>tr>.tableblock{border-width:0 0 1px} -table.grid-rows>tfoot>tr>.tableblock{border-width:1px 0 0} -table.grid-all>*>tr>.tableblock:last-child,table.grid-cols>*>tr>.tableblock:last-child{border-right-width:0} -table.grid-all>tbody>tr:last-child>.tableblock,table.grid-all>thead:last-child>tr>.tableblock,table.grid-rows>tbody>tr:last-child>.tableblock,table.grid-rows>thead:last-child>tr>.tableblock{border-bottom-width:0} -table.frame-all{border-width:1px} -table.frame-sides{border-width:0 1px} -table.frame-topbot,table.frame-ends{border-width:1px 0} -table.stripes-all tr,table.stripes-odd tr:nth-of-type(odd){background:#f8f8f7} -table.stripes-none tr,table.stripes-odd tr:nth-of-type(even){background:none} -th.halign-left,td.halign-left{text-align:left} -th.halign-right,td.halign-right{text-align:right} -th.halign-center,td.halign-center{text-align:center} -th.valign-top,td.valign-top{vertical-align:top} -th.valign-bottom,td.valign-bottom{vertical-align:bottom} -th.valign-middle,td.valign-middle{vertical-align:middle} -table thead th,table tfoot th{font-weight:bold} -tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7} -tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold} -p.tableblock>code:only-child{background:none;padding:0} -p.tableblock{font-size:1em} -td>div.verse{white-space:pre} -ol{margin-left:1.75em} -ul li ol{margin-left:1.5em} -dl dd{margin-left:1.125em} -dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0} -ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em} -ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none} -ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em} -ul.unstyled,ol.unstyled{margin-left:0} -ul.checklist{margin-left:.625em} -ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em} -ul.checklist li>p:first-child>input[type="checkbox"]:first-child{margin-right:.25em} -ul.inline{display:-ms-flexbox;display:-webkit-box;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em} -ul.inline>li{margin-left:1.25em} -.unstyled dl dt{font-weight:400;font-style:normal} -ol.arabic{list-style-type:decimal} -ol.decimal{list-style-type:decimal-leading-zero} -ol.loweralpha{list-style-type:lower-alpha} -ol.upperalpha{list-style-type:upper-alpha} -ol.lowerroman{list-style-type:lower-roman} -ol.upperroman{list-style-type:upper-roman} -ol.lowergreek{list-style-type:lower-greek} -.hdlist>table,.colist>table{border:0;background:none} -.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none} -td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em} -td.hdlist1{font-weight:bold;padding-bottom:1.25em} -.literalblock+.colist,.listingblock+.colist{margin-top:-.5em} -.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top} -.colist td:not([class]):first-child img{max-width:none} -.colist td:not([class]):last-child{padding:.25em 0} -.thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd} -.imageblock.left{margin:.25em .625em 1.25em 0} -.imageblock.right{margin:.25em 0 1.25em .625em} -.imageblock>.title{margin-bottom:0} -.imageblock.thumb,.imageblock.th{border-width:6px} -.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em} -.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0} -.image.left{margin-right:.625em} -.image.right{margin-left:.625em} -a.image{text-decoration:none;display:inline-block} -a.image object{pointer-events:none} -sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super} -sup.footnote a,sup.footnoteref a{text-decoration:none} -sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline} -#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em} -#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0} -#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em} -#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em} -#footnotes .footnote:last-of-type{margin-bottom:0} -#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0} -.gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0} -.gist .file-data>table td.line-data{width:99%} -div.unbreakable{page-break-inside:avoid} -.big{font-size:larger} -.small{font-size:smaller} -.underline{text-decoration:underline} -.overline{text-decoration:overline} -.line-through{text-decoration:line-through} -.aqua{color:#00bfbf} -.aqua-background{background-color:#00fafa} -.black{color:#000} -.black-background{background-color:#000} -.blue{color:#0000bf} -.blue-background{background-color:#0000fa} -.fuchsia{color:#bf00bf} -.fuchsia-background{background-color:#fa00fa} -.gray{color:#606060} -.gray-background{background-color:#7d7d7d} -.green{color:#006000} -.green-background{background-color:#007d00} -.lime{color:#00bf00} -.lime-background{background-color:#00fa00} -.maroon{color:#600000} -.maroon-background{background-color:#7d0000} -.navy{color:#000060} -.navy-background{background-color:#00007d} -.olive{color:#606000} -.olive-background{background-color:#7d7d00} -.purple{color:#600060} -.purple-background{background-color:#7d007d} -.red{color:#bf0000} -.red-background{background-color:#fa0000} -.silver{color:#909090} -.silver-background{background-color:#bcbcbc} -.teal{color:#006060} -.teal-background{background-color:#007d7d} -.white{color:#bfbfbf} -.white-background{background-color:#fafafa} -.yellow{color:#bfbf00} -.yellow-background{background-color:#fafa00} -span.icon>.fa{cursor:default} -a span.icon>.fa{cursor:inherit} -.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default} -.admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c} -.admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111} -.admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900} -.admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400} -.admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000} -.conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold} -.conum[data-value] *{color:#fff!important} -.conum[data-value]+b{display:none} -.conum[data-value]::after{content:attr(data-value)} -pre .conum[data-value]{position:relative;top:-.125em} -b.conum *{color:inherit!important} -.conum:not([data-value]):empty{display:none} -dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility} -h1,h2,p,td.content,span.alt{letter-spacing:-.01em} -p strong,td.content strong,div.footnote strong{letter-spacing:-.005em} -p,blockquote,dt,td.content,span.alt{font-size:1.0625rem} -p{margin-bottom:1.25rem} -.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em} -.exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc} -.print-only{display:none!important} -@page{margin:1.25cm .75cm} -@media print{*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important} -html{font-size:80%} -a{color:inherit!important;text-decoration:underline!important} -a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important} -a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em} -abbr[title]::after{content:" (" attr(title) ")"} -pre,blockquote,tr,img,object,svg{page-break-inside:avoid} -thead{display:table-header-group} -svg{max-width:100%} -p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3} -h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid} -#toc,.sidebarblock,.exampleblock>.content{background:none!important} -#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important} -body.book #header{text-align:center} -body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em} -body.book #header .details{border:0!important;display:block;padding:0!important} -body.book #header .details span:first-child{margin-left:0!important} -body.book #header .details br{display:block} -body.book #header .details br+span::before{content:none!important} -body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important} -body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always} -.listingblock code[data-lang]::before{display:block} -#footer{padding:0 .9375em} -.hide-on-print{display:none!important} -.print-only{display:block!important} -.hide-for-print{display:none!important} -.show-for-print{display:inherit!important}} -@media print,amzn-kf8{#header>h1:first-child{margin-top:1.25rem} -.sect1{padding:0!important} -.sect1+.sect1{border:0} -#footer{background:none} -#footer-text{color:rgba(0,0,0,.6);font-size:.9em}} -@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}} - -/* Zajo's customizations applied on top of the standard asciidoctor css above */ -h1{font-size:4em} -h2{font-size:1.74em} -h3,#toctitle,.sidebarblock>.content>.title{font-size:1.5em} -h4{font-size:1.2em} -h5{font-size:1em} -h6{font-size:1em} -#toc {text-align:left} -#toc ul code{font-size:111%} -#toc a:hover code {color:#00cc99} -a:focus{outline:0} -.colist td{color:rgba(255,255,255,.67)} -body{text-align:left; background:#202020;color:rgba(255,255,255,.67);padding:0;margin:0;font-family:"Istok Web","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto;tab-size:4;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased} -.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#a0a0a0;font-weight:400;margin-top:0;margin-bottom:.25em} -.literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#101010} -table{background:#202020;margin-bottom:1.25em;border:solid 1px #dedede} -table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(255,255,255,.67)} -table tr.even,table tr.alt,table tr:nth-of-type(even){background:#202020} -table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{color:rgba(255,255,255,.67)} -th{background-color:#404040} -a{color:#FFFFFF;text-decoration:underline;line-height:inherit} -a:hover{color:#00cc99} -a:focus{color:#FFFFFF} -h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Quicksand","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#00cc99;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.4em} -code{font-family:"Anonymous Pro","DejaVu Sans Mono",monospace;font-weight:400;color:black} -*:not(pre)>code{font-size:1.0em;font-style:normal!important;letter-spacing:0;padding:0 0;word-spacing:-.15em;background-color:transparent;-webkit-border-radius:0;border-radius:0;line-height:1.45;text-rendering:optimizeLegibility;word-wrap:break-word;color:white} -pre,pre>code{line-height:1.45;color:rgba(255,255,255,.67);font-family:"Anonymous Pro","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeLegibility;font-size:1.05em;background-color:#101010} -a:not(pre)>code:hover {color:#00cc99} -kbd{font-family:"Anonymous Pro","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap} -h1 code{color:#00cc99; font-size:113%} -h2 code{color:#00cc99; font-size:113%} -h3 code{color:#00cc99; font-size:113%} -h4 code{color:#00cc99; font-size:113%} -h5 code{color:#00cc99; font-size:113%} -#header>h1:first-child{font-family:"Poiret One";color:#00cc99;margin-top:2.25rem;margin-bottom:0;letter-spacing:-.07em} -#author{color:#a366ff} -#toc ul{font-family:"Quicksand","DejaVu Sans",sans-serif;list-style-type:none} -#toc a:hover{color:#00cc99} -#toc.toc2{background-color:#404040} -.admonitionblock td.icon .icon-note::before{content:"\f05a";color:#00cc99} -.admonitionblock td.icon .icon-tip::before{content:"\f0eb";color:#00cc99;text-shadow:none} -.admonitionblock td.icon .icon-warning::before{content:"\f071";color:#a366ff} -.admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#a366ff} -.admonitionblock td.icon .icon-important::before{content:"\f06a";color:#a366ff} -.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(255,255,255,.67)} -.conum[data-value]{display:inline-block;color:black!important;background-color:#d9d9d9;-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold} -.exampleblock>.content{background-color:#404040;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc} -.quoteblock {background-color:#404040} -.quoteblock blockquote,.quoteblock p{color:rgba(255,255,255,.67);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify;background-color:#404040} -.quoteblock blockquote::before{margin-left:-.8em;color:#00cc99} -.quoteblock blockquote{font-family:"Istok Web","DejaVu Serif"; font-size:1.0625rem; padding:0.5em} -.quoteblock .attribution{padding-top:.75ex;margin-top:0;margin-right:0;padding-right:.5ex;text-align:right;background-color:#202020} -.text-right{margin-top:-1em} diff --git a/doc/html/zajo-light.css b/doc/html/zajo-light.css deleted file mode 100644 index 89a5cdaf..00000000 --- a/doc/html/zajo-light.css +++ /dev/null @@ -1,468 +0,0 @@ -/* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */ -/* Uncomment @import statement below to use as custom stylesheet */ -/*@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700";*/ - -/* Zajo's custom font import. The rest of the customizations are at the bottom of this css file, which is otherwise kept unchanged */ -@import "https://fonts.googleapis.com/css?family=Anonymous+Pro|Istok+Web|Quicksand|Poiret+One"; - -article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block} -audio,canvas,video{display:inline-block} -audio:not([controls]){display:none;height:0} -script{display:none!important} -html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%} -a{background:transparent} -a:focus{outline:thin dotted} -a:active,a:hover{outline:0} -h1{font-size:2em;margin:.67em 0} -abbr[title]{border-bottom:1px dotted} -b,strong{font-weight:bold} -dfn{font-style:italic} -hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0} -mark{background:#ff0;color:#000} -code,kbd,pre,samp{font-family:monospace;font-size:1em} -pre{white-space:pre-wrap} -q{quotes:"\201C" "\201D" "\2018" "\2019"} -small{font-size:80%} -sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline} -sup{top:-.5em} -sub{bottom:-.25em} -img{border:0} -svg:not(:root){overflow:hidden} -figure{margin:0} -fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em} -legend{border:0;padding:0} -button,input,select,textarea{font-family:inherit;font-size:100%;margin:0} -button,input{line-height:normal} -button,select{text-transform:none} -button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer} -button[disabled],html input[disabled]{cursor:default} -input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0} -button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0} -textarea{overflow:auto;vertical-align:top} -table{border-collapse:collapse;border-spacing:0} -*,*::before,*::after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box} -html,body{font-size:100%} -body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto;tab-size:4;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased} -a:hover{cursor:pointer} -img,object,embed{max-width:100%;height:auto} -object,embed{height:100%} -img{-ms-interpolation-mode:bicubic} -.left{float:left!important} -.right{float:right!important} -.text-left{text-align:left!important} -.text-right{text-align:right!important} -.text-center{text-align:center!important} -.text-justify{text-align:justify!important} -.hide{display:none} -img,object,svg{display:inline-block;vertical-align:middle} -textarea{height:auto;min-height:50px} -select{width:100%} -.center{margin-left:auto;margin-right:auto} -.stretch{width:100%} -.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em} -div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr} -a{color:#2156a5;text-decoration:underline;line-height:inherit} -a:hover,a:focus{color:#1d4b8f} -a img{border:none} -p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility} -p aside{font-size:.875em;line-height:1.35;font-style:italic} -h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em} -h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0} -h1{font-size:2.125em} -h2{font-size:1.6875em} -h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em} -h4,h5{font-size:1.125em} -h6{font-size:1em} -hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0} -em,i{font-style:italic;line-height:inherit} -strong,b{font-weight:bold;line-height:inherit} -small{font-size:60%;line-height:inherit} -code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)} -ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit} -ul,ol{margin-left:1.5em} -ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em} -ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit} -ul.square{list-style-type:square} -ul.circle{list-style-type:circle} -ul.disc{list-style-type:disc} -ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0} -dl dt{margin-bottom:.3125em;font-weight:bold} -dl dd{margin-bottom:1.25em} -abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help} -abbr{text-transform:none} -blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd} -blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)} -blockquote cite::before{content:"\2014 \0020"} -blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)} -blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)} -@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2} -h1{font-size:2.75em} -h2{font-size:2.3125em} -h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em} -h4{font-size:1.4375em}} -table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede} -table thead,table tfoot{background:#f7f8f7} -table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left} -table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)} -table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7} -table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6} -h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em} -h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400} -.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table} -.clearfix::after,.float-group::after{clear:both} -*:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed;word-wrap:break-word} -*:not(pre)>code.nobreak{word-wrap:normal} -*:not(pre)>code.nowrap{white-space:nowrap} -pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeSpeed} -em em{font-style:normal} -strong strong{font-weight:400} -.keyseq{color:rgba(51,51,51,.8)} -kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap} -.keyseq kbd:first-child{margin-left:0} -.keyseq kbd:last-child{margin-right:0} -.menuseq,.menuref{color:#000} -.menuseq b:not(.caret),.menuref{font-weight:inherit} -.menuseq{word-spacing:-.02em} -.menuseq b.caret{font-size:1.25em;line-height:.8} -.menuseq i.caret{font-weight:bold;text-align:center;width:.45em} -b.button::before,b.button::after{position:relative;top:-1px;font-weight:400} -b.button::before{content:"[";padding:0 3px 0 2px} -b.button::after{content:"]";padding:0 2px 0 3px} -p a>code:hover{color:rgba(0,0,0,.9)} -#header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em} -#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table} -#header::after,#content::after,#footnotes::after,#footer::after{clear:both} -#content{margin-top:1.25em} -#content::before{content:none} -#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0} -#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf} -#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px} -#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap} -#header .details span:first-child{margin-left:-.125em} -#header .details span.email a{color:rgba(0,0,0,.85)} -#header .details br{display:none} -#header .details br+span::before{content:"\00a0\2013\00a0"} -#header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)} -#header .details br+span#revremark::before{content:"\00a0|\00a0"} -#header #revnumber{text-transform:capitalize} -#header #revnumber::after{content:"\00a0"} -#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem} -#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em} -#toc>ul{margin-left:.125em} -#toc ul.sectlevel0>li>a{font-style:italic} -#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0} -#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none} -#toc li{line-height:1.3334;margin-top:.3334em} -#toc a{text-decoration:none} -#toc a:active{text-decoration:underline} -#toctitle{color:#7a2518;font-size:1.2em} -@media screen and (min-width:768px){#toctitle{font-size:1.375em} -body.toc2{padding-left:15em;padding-right:0} -#toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto} -#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em} -#toc.toc2>ul{font-size:.9em;margin-bottom:0} -#toc.toc2 ul ul{margin-left:0;padding-left:1em} -#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em} -body.toc2.toc-right{padding-left:0;padding-right:15em} -body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}} -@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0} -#toc.toc2{width:20em} -#toc.toc2 #toctitle{font-size:1.375em} -#toc.toc2>ul{font-size:.95em} -#toc.toc2 ul ul{padding-left:1.25em} -body.toc2.toc-right{padding-left:0;padding-right:20em}} -#content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px} -#content #toc>:first-child{margin-top:0} -#content #toc>:last-child{margin-bottom:0} -#footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em} -#footer-text{color:rgba(255,255,255,.8);line-height:1.44} -#content{margin-bottom:.625em} -.sect1{padding-bottom:.625em} -@media screen and (min-width:768px){#content{margin-bottom:1.25em} -.sect1{padding-bottom:1.25em}} -.sect1:last-child{padding-bottom:0} -.sect1+.sect1{border-top:1px solid #e7e7e9} -#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400} -#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em} -#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible} -#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none} -#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221} -.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em} -.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic} -table.tableblock.fit-content>caption.title{white-space:nowrap;width:0} -.paragraph.lead>p,#preamble>.sectionbody>[class="paragraph"]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)} -table.tableblock #preamble>.sectionbody>[class="paragraph"]:first-of-type p{font-size:inherit} -.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%} -.admonitionblock>table td.icon{text-align:center;width:80px} -.admonitionblock>table td.icon img{max-width:none} -.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase} -.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6)} -.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0} -.exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px} -.exampleblock>.content>:first-child{margin-top:0} -.exampleblock>.content>:last-child{margin-bottom:0} -.sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px} -.sidebarblock>:first-child{margin-top:0} -.sidebarblock>:last-child{margin-bottom:0} -.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center} -.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0} -.literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8} -.sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class="highlight"],.sidebarblock .listingblock pre[class^="highlight "],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1} -.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;overflow-x:auto;padding:1em;font-size:.8125em} -@media screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}} -@media screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}} -.literalblock pre.nowrap,.literalblock pre.nowrap pre,.listingblock pre.nowrap,.listingblock pre.nowrap pre{white-space:pre;word-wrap:normal} -.literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)} -.listingblock pre.highlightjs{padding:0} -.listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px} -.listingblock pre.prettyprint{border-width:0} -.listingblock>.content{position:relative} -.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999} -.listingblock:hover code[data-lang]::before{display:block} -.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:#999} -.listingblock.terminal pre .command:not([data-prompt])::before{content:"$"} -table.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none} -table.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45} -table.pyhltable td.code{padding-left:.75em;padding-right:0} -pre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #dddddf} -pre.pygments .lineno{display:inline-block;margin-right:.25em} -table.pyhltable .linenodiv{background:none!important;padding-right:0!important} -.quoteblock{margin:0 1em 1.25em 1.5em;display:table} -.quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em} -.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify} -.quoteblock blockquote{margin:0;padding:0;border:0} -.quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)} -.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0} -.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right} -.verseblock{margin:0 1em 1.25em} -.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility} -.verseblock pre strong{font-weight:400} -.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex} -.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic} -.quoteblock .attribution br,.verseblock .attribution br{display:none} -.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)} -.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none} -.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0} -.quoteblock.abstract{margin:0 1em 1.25em;display:block} -.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center} -.quoteblock.excerpt,.quoteblock .quoteblock{margin:0 0 1.25em;padding:0 0 .25em 1em;border-left:.25em solid #dddddf} -.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem} -.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;text-align:left;margin-right:0} -table.tableblock{max-width:100%;border-collapse:separate} -p.tableblock:last-child{margin-bottom:0} -td.tableblock>.content{margin-bottom:-1.25em} -table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede} -table.grid-all>thead>tr>.tableblock,table.grid-all>tbody>tr>.tableblock{border-width:0 1px 1px 0} -table.grid-all>tfoot>tr>.tableblock{border-width:1px 1px 0 0} -table.grid-cols>*>tr>.tableblock{border-width:0 1px 0 0} -table.grid-rows>thead>tr>.tableblock,table.grid-rows>tbody>tr>.tableblock{border-width:0 0 1px} -table.grid-rows>tfoot>tr>.tableblock{border-width:1px 0 0} -table.grid-all>*>tr>.tableblock:last-child,table.grid-cols>*>tr>.tableblock:last-child{border-right-width:0} -table.grid-all>tbody>tr:last-child>.tableblock,table.grid-all>thead:last-child>tr>.tableblock,table.grid-rows>tbody>tr:last-child>.tableblock,table.grid-rows>thead:last-child>tr>.tableblock{border-bottom-width:0} -table.frame-all{border-width:1px} -table.frame-sides{border-width:0 1px} -table.frame-topbot,table.frame-ends{border-width:1px 0} -table.stripes-all tr,table.stripes-odd tr:nth-of-type(odd){background:#f8f8f7} -table.stripes-none tr,table.stripes-odd tr:nth-of-type(even){background:none} -th.halign-left,td.halign-left{text-align:left} -th.halign-right,td.halign-right{text-align:right} -th.halign-center,td.halign-center{text-align:center} -th.valign-top,td.valign-top{vertical-align:top} -th.valign-bottom,td.valign-bottom{vertical-align:bottom} -th.valign-middle,td.valign-middle{vertical-align:middle} -table thead th,table tfoot th{font-weight:bold} -tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7} -tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold} -p.tableblock>code:only-child{background:none;padding:0} -p.tableblock{font-size:1em} -td>div.verse{white-space:pre} -ol{margin-left:1.75em} -ul li ol{margin-left:1.5em} -dl dd{margin-left:1.125em} -dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0} -ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em} -ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none} -ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em} -ul.unstyled,ol.unstyled{margin-left:0} -ul.checklist{margin-left:.625em} -ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em} -ul.checklist li>p:first-child>input[type="checkbox"]:first-child{margin-right:.25em} -ul.inline{display:-ms-flexbox;display:-webkit-box;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em} -ul.inline>li{margin-left:1.25em} -.unstyled dl dt{font-weight:400;font-style:normal} -ol.arabic{list-style-type:decimal} -ol.decimal{list-style-type:decimal-leading-zero} -ol.loweralpha{list-style-type:lower-alpha} -ol.upperalpha{list-style-type:upper-alpha} -ol.lowerroman{list-style-type:lower-roman} -ol.upperroman{list-style-type:upper-roman} -ol.lowergreek{list-style-type:lower-greek} -.hdlist>table,.colist>table{border:0;background:none} -.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none} -td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em} -td.hdlist1{font-weight:bold;padding-bottom:1.25em} -.literalblock+.colist,.listingblock+.colist{margin-top:-.5em} -.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top} -.colist td:not([class]):first-child img{max-width:none} -.colist td:not([class]):last-child{padding:.25em 0} -.thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd} -.imageblock.left{margin:.25em .625em 1.25em 0} -.imageblock.right{margin:.25em 0 1.25em .625em} -.imageblock>.title{margin-bottom:0} -.imageblock.thumb,.imageblock.th{border-width:6px} -.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em} -.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0} -.image.left{margin-right:.625em} -.image.right{margin-left:.625em} -a.image{text-decoration:none;display:inline-block} -a.image object{pointer-events:none} -sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super} -sup.footnote a,sup.footnoteref a{text-decoration:none} -sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline} -#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em} -#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0} -#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em} -#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em} -#footnotes .footnote:last-of-type{margin-bottom:0} -#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0} -.gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0} -.gist .file-data>table td.line-data{width:99%} -div.unbreakable{page-break-inside:avoid} -.big{font-size:larger} -.small{font-size:smaller} -.underline{text-decoration:underline} -.overline{text-decoration:overline} -.line-through{text-decoration:line-through} -.aqua{color:#00bfbf} -.aqua-background{background-color:#00fafa} -.black{color:#000} -.black-background{background-color:#000} -.blue{color:#0000bf} -.blue-background{background-color:#0000fa} -.fuchsia{color:#bf00bf} -.fuchsia-background{background-color:#fa00fa} -.gray{color:#606060} -.gray-background{background-color:#7d7d7d} -.green{color:#006000} -.green-background{background-color:#007d00} -.lime{color:#00bf00} -.lime-background{background-color:#00fa00} -.maroon{color:#600000} -.maroon-background{background-color:#7d0000} -.navy{color:#000060} -.navy-background{background-color:#00007d} -.olive{color:#606000} -.olive-background{background-color:#7d7d00} -.purple{color:#600060} -.purple-background{background-color:#7d007d} -.red{color:#bf0000} -.red-background{background-color:#fa0000} -.silver{color:#909090} -.silver-background{background-color:#bcbcbc} -.teal{color:#006060} -.teal-background{background-color:#007d7d} -.white{color:#bfbfbf} -.white-background{background-color:#fafafa} -.yellow{color:#bfbf00} -.yellow-background{background-color:#fafa00} -span.icon>.fa{cursor:default} -a span.icon>.fa{cursor:inherit} -.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default} -.admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c} -.admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111} -.admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900} -.admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400} -.admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000} -.conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold} -.conum[data-value] *{color:#fff!important} -.conum[data-value]+b{display:none} -.conum[data-value]::after{content:attr(data-value)} -pre .conum[data-value]{position:relative;top:-.125em} -b.conum *{color:inherit!important} -.conum:not([data-value]):empty{display:none} -dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility} -h1,h2,p,td.content,span.alt{letter-spacing:-.01em} -p strong,td.content strong,div.footnote strong{letter-spacing:-.005em} -p,blockquote,dt,td.content,span.alt{font-size:1.0625rem} -p{margin-bottom:1.25rem} -.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em} -.exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc} -.print-only{display:none!important} -@page{margin:1.25cm .75cm} -@media print{*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important} -html{font-size:80%} -a{color:inherit!important;text-decoration:underline!important} -a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important} -a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em} -abbr[title]::after{content:" (" attr(title) ")"} -pre,blockquote,tr,img,object,svg{page-break-inside:avoid} -thead{display:table-header-group} -svg{max-width:100%} -p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3} -h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid} -#toc,.sidebarblock,.exampleblock>.content{background:none!important} -#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important} -body.book #header{text-align:center} -body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em} -body.book #header .details{border:0!important;display:block;padding:0!important} -body.book #header .details span:first-child{margin-left:0!important} -body.book #header .details br{display:block} -body.book #header .details br+span::before{content:none!important} -body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important} -body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always} -.listingblock code[data-lang]::before{display:block} -#footer{padding:0 .9375em} -.hide-on-print{display:none!important} -.print-only{display:block!important} -.hide-for-print{display:none!important} -.show-for-print{display:inherit!important}} -@media print,amzn-kf8{#header>h1:first-child{margin-top:1.25rem} -.sect1{padding:0!important} -.sect1+.sect1{border:0} -#footer{background:none} -#footer-text{color:rgba(0,0,0,.6);font-size:.9em}} -@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}} - -/* Zajo's customizations applied on top of the standard asciidoctor css above */ -h1{font-size:4em} -h2{font-size:1.74em} -h3,#toctitle,.sidebarblock>.content>.title{font-size:1.5em} -h4{font-size:1.2em} -h5{font-size:1em} -h6{font-size:1em} -#toc {text-align:left} -#toc ul code{font-size:111%} -#toc a:hover code {color:#4101a7} -a:focus{outline:0} -.colist td{color:rgba(0,0,0,.67)} -body{text-align:left; background:#fff;color:rgba(0,0,0,.67);padding:0;margin:0;font-family:"Istok Web","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto;tab-size:4;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased} -.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#a0a0a0;font-weight:400;margin-top:0;margin-bottom:.25em} -a{color:#000000;text-decoration:underline;line-height:inherit} -a:hover{color:#4101a7} -a:focus{color:#000000} -h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Quicksand","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#4101a7;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.4em} -code{font-family:"Anonymous Pro","DejaVu Sans Mono",monospace;font-weight:400;color:black} -*:not(pre)>code{font-size:1.0em;font-style:normal!important;letter-spacing:0;padding:0 0;word-spacing:-.15em;background-color:transparent;-webkit-border-radius:0;border-radius:0;line-height:1.45;text-rendering:optimizeLegibility;word-wrap:break-word} -pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Anonymous Pro","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeLegibility;font-size:1.05em;background-color:#f7f8f7} -a:not(pre)>code:hover {color:#4101a7} -kbd{font-family:"Anonymous Pro","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap} -h1 code{color:#4101a7; font-size:113%} -h2 code{color:#4101a7; font-size:113%} -h3 code{color:#4101a7; font-size:113%} -h4 code{color:#4101a7; font-size:113%} -h5 code{color:#4101a7; font-size:113%} -#header>h1:first-child{font-family:"Poiret One";color:#ff5100;margin-top:2.25rem;margin-bottom:0;letter-spacing:-.07em} -#author{color: #4101a7;} -#toc ul{font-family:"Quicksand","DejaVu Sans",sans-serif;list-style-type:none} -#toc a:hover{color:#4101a7} -#toc.toc2{background-color:#f7f8f7} -.admonitionblock td.icon .icon-note::before{content:"\f05a";color:#606060} -.admonitionblock td.icon .icon-tip::before{content:"\f0eb";color:#606060;text-shadow:none} -.admonitionblock td.icon .icon-warning::before{content:"\f071";color:#ff5100} -.admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#ff5100} -.admonitionblock td.icon .icon-important::before{content:"\f06a";color:#ff5100} -.conum[data-value]{display:inline-block;color:#fff!important;background-color:#606060;-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold} -.exampleblock>.content{background-color:#ffffff;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc} -.quoteblock blockquote::before{margin-left:-.8em;color:#4101a7} -.quoteblock blockquote{font-family:"Istok Web","DejaVu Serif"; font-size:1.0625rem; padding:0.5em} -.text-right{margin-top:-1em} diff --git a/doc/local-playbook.yml b/doc/local-playbook.yml index 69191e68..005c376f 100644 --- a/doc/local-playbook.yml +++ b/doc/local-playbook.yml @@ -29,6 +29,9 @@ ui: url: https://github.com/boostorg/website-v2-docs/releases/download/ui-master/ui-bundle.zip snapshot: true +output: + dir: html + antora: extensions: - require: '@antora/lunr-extension' # https://gitlab.com/antora/antora-lunr-extension