mirror of
https://github.com/boostorg/openmethod.git
synced 2026-01-19 04:22:12 +00:00
inception
This commit is contained in:
136
.clang-format
Normal file
136
.clang-format
Normal file
@@ -0,0 +1,136 @@
|
||||
---
|
||||
Language: Cpp
|
||||
# BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -2
|
||||
AlignAfterOpenBracket: AlwaysBreak
|
||||
AlignConsecutiveMacros: false
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: false
|
||||
AlignTrailingComments: true
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllConstructorInitializersOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: false
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: true
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: false
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 80
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DeriveLineEnding: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: true
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
|
||||
Priority: 3
|
||||
SortPriority: 0
|
||||
- Regex: '.*'
|
||||
Priority: 1
|
||||
SortPriority: 0
|
||||
IncludeIsMainRegex: '(Test)?$'
|
||||
IncludeIsMainSourceRegex: ''
|
||||
IndentCaseLabels: false
|
||||
IndentGotoLabels: true
|
||||
#IndentPPDirectives: true
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBinPackProtocolList: Auto
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PointerAlignment: Left
|
||||
ReflowComments: false
|
||||
SortIncludes: false
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: false
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyBlock: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInConditionalStatement: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
SpaceBeforeSquareBrackets: false
|
||||
Standard: Latest
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
TabWidth: 8
|
||||
UseCRLF: false
|
||||
UseTab: Never
|
||||
...
|
||||
33
.clang-tidy
Normal file
33
.clang-tidy
Normal file
@@ -0,0 +1,33 @@
|
||||
---
|
||||
Checks: 'clang-diagnostic-*,clang-analyzer-*,modernize-use-trailing-return-type'
|
||||
WarningsAsErrors: ''
|
||||
HeaderFileExtensions:
|
||||
- ''
|
||||
- h
|
||||
- hh
|
||||
- hpp
|
||||
- hxx
|
||||
ImplementationFileExtensions:
|
||||
- c
|
||||
- cc
|
||||
- cpp
|
||||
- cxx
|
||||
ExcludeHeaderFilterRegex: ''
|
||||
FormatStyle: file
|
||||
User: jll
|
||||
CheckOptions:
|
||||
cert-dcl16-c.NewSuffixes: 'L;LL;LU;LLU'
|
||||
cert-err33-c.AllowCastToVoid: 'true'
|
||||
cert-err33-c.CheckedFunctions: '^::aligned_alloc;^::asctime_s;^::at_quick_exit;^::atexit;^::bsearch;^::bsearch_s;^::btowc;^::c16rtomb;^::c32rtomb;^::calloc;^::clock;^::cnd_broadcast;^::cnd_init;^::cnd_signal;^::cnd_timedwait;^::cnd_wait;^::ctime_s;^::fclose;^::fflush;^::fgetc;^::fgetpos;^::fgets;^::fgetwc;^::fopen;^::fopen_s;^::fprintf;^::fprintf_s;^::fputc;^::fputs;^::fputwc;^::fputws;^::fread;^::freopen;^::freopen_s;^::fscanf;^::fscanf_s;^::fseek;^::fsetpos;^::ftell;^::fwprintf;^::fwprintf_s;^::fwrite;^::fwscanf;^::fwscanf_s;^::getc;^::getchar;^::getenv;^::getenv_s;^::gets_s;^::getwc;^::getwchar;^::gmtime;^::gmtime_s;^::localtime;^::localtime_s;^::malloc;^::mbrtoc16;^::mbrtoc32;^::mbsrtowcs;^::mbsrtowcs_s;^::mbstowcs;^::mbstowcs_s;^::memchr;^::mktime;^::mtx_init;^::mtx_lock;^::mtx_timedlock;^::mtx_trylock;^::mtx_unlock;^::printf_s;^::putc;^::putwc;^::raise;^::realloc;^::remove;^::rename;^::scanf;^::scanf_s;^::setlocale;^::setvbuf;^::signal;^::snprintf;^::snprintf_s;^::sprintf;^::sprintf_s;^::sscanf;^::sscanf_s;^::strchr;^::strerror_s;^::strftime;^::strpbrk;^::strrchr;^::strstr;^::strtod;^::strtof;^::strtoimax;^::strtok;^::strtok_s;^::strtol;^::strtold;^::strtoll;^::strtoul;^::strtoull;^::strtoumax;^::strxfrm;^::swprintf;^::swprintf_s;^::swscanf;^::swscanf_s;^::thrd_create;^::thrd_detach;^::thrd_join;^::thrd_sleep;^::time;^::timespec_get;^::tmpfile;^::tmpfile_s;^::tmpnam;^::tmpnam_s;^::tss_create;^::tss_get;^::tss_set;^::ungetc;^::ungetwc;^::vfprintf;^::vfprintf_s;^::vfscanf;^::vfscanf_s;^::vfwprintf;^::vfwprintf_s;^::vfwscanf;^::vfwscanf_s;^::vprintf_s;^::vscanf;^::vscanf_s;^::vsnprintf;^::vsnprintf_s;^::vsprintf;^::vsprintf_s;^::vsscanf;^::vsscanf_s;^::vswprintf;^::vswprintf_s;^::vswscanf;^::vswscanf_s;^::vwprintf_s;^::vwscanf;^::vwscanf_s;^::wcrtomb;^::wcschr;^::wcsftime;^::wcspbrk;^::wcsrchr;^::wcsrtombs;^::wcsrtombs_s;^::wcsstr;^::wcstod;^::wcstof;^::wcstoimax;^::wcstok;^::wcstok_s;^::wcstol;^::wcstold;^::wcstoll;^::wcstombs;^::wcstombs_s;^::wcstoul;^::wcstoull;^::wcstoumax;^::wcsxfrm;^::wctob;^::wctrans;^::wctype;^::wmemchr;^::wprintf_s;^::wscanf;^::wscanf_s;'
|
||||
cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField: 'false'
|
||||
cert-str34-c.DiagnoseSignedUnsignedCharComparisons: 'false'
|
||||
cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic: 'true'
|
||||
google-readability-braces-around-statements.ShortStatementLines: '1'
|
||||
google-readability-function-size.StatementThreshold: '800'
|
||||
google-readability-namespace-comments.ShortNamespaceLines: '10'
|
||||
google-readability-namespace-comments.SpacesBeforeComments: '2'
|
||||
llvm-else-after-return.WarnOnConditionVariables: 'false'
|
||||
llvm-else-after-return.WarnOnUnfixable: 'false'
|
||||
llvm-qualified-auto.AddConstToQualified: 'false'
|
||||
SystemHeaders: false
|
||||
...
|
||||
122
.github/workflows/main.yml
vendored
Normal file
122
.github/workflows/main.yml
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
# Copyright (c) 2018-2025 Jean-Louis Leroy
|
||||
# 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)
|
||||
|
||||
# CI is quite simple at the moment. It will be improved and made more
|
||||
# comprehensive, probably similar to Boost.Unordered.
|
||||
|
||||
name: CI
|
||||
|
||||
env:
|
||||
BUILD_TYPE: Debug Release
|
||||
|
||||
permissions:
|
||||
contents: 'read'
|
||||
pages: 'write'
|
||||
id-token: 'write'
|
||||
|
||||
on: [push, pull_request, workflow_dispatch]
|
||||
|
||||
jobs:
|
||||
Ubuntu:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
config: [Debug, Release]
|
||||
compiler: [clang++, g++]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install clang++
|
||||
run: |
|
||||
wget https://apt.llvm.org/llvm.sh
|
||||
chmod +x llvm.sh
|
||||
sudo ./llvm.sh $1
|
||||
if: matrix.compiler == 'clang++'
|
||||
- name: Install Boost
|
||||
run: sudo apt-get install -y libboost-all-dev
|
||||
- name: Configure
|
||||
run: cmake -DCMAKE_BUILD_TYPE=${{ matrix.config }} -DCMAKE_CXX_COMPILER=${{ matrix.compiler }} -DBUILD_TESTING=1 -DBUILD_EXAMPLES=1 -Bbuild
|
||||
- name: Build
|
||||
run: cmake --build build
|
||||
- name: Test
|
||||
run: |
|
||||
ctest --test-dir build --rerun-failed --output-on-failure
|
||||
Windows:
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
config: [Debug, Release]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ilammy/msvc-dev-cmd@v1
|
||||
- name: Install boost
|
||||
uses: MarkusJx/install-boost@v2
|
||||
id: install-boost
|
||||
with:
|
||||
boost_version: 1.87.0
|
||||
- name: Configure
|
||||
run: |
|
||||
cmake -DCMAKE_BUILD_TYPE=${{ matrix.config }} -DBUILD_TESTING=1 -DBUILD_EXAMPLES=1 -Bbuild -DBoost_DIR=${{ steps.install-boost.outputs.BOOST_ROOT }} -DBoost_INCLUDE_DIR=${{steps.install-boost.outputs.BOOST_ROOT}}\include -DBoost_LIBRARY_DIRS=${{steps.install-boost.outputs.BOOST_ROOT}}\lib
|
||||
env:
|
||||
BOOST_ROOT: ${{ steps.install-boost.outputs.BOOST_ROOT }}
|
||||
- name: Build
|
||||
run: cmake --build build --config ${{ matrix.config }}
|
||||
- name: Test
|
||||
run: |
|
||||
ctest --test-dir build --rerun-failed --output-on-failure -C ${{ matrix.config }}
|
||||
MacOS:
|
||||
runs-on: macos-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
config: [Debug, Release]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ilammy/msvc-dev-cmd@v1
|
||||
- name: Install boost
|
||||
run: brew install boost
|
||||
- name: Configure
|
||||
run: |
|
||||
cmake -DCMAKE_BUILD_TYPE=${{ matrix.config }} -DBUILD_TESTING=1 -DBUILD_EXAMPLES=1 -Bbuild
|
||||
- name: Build
|
||||
run: |
|
||||
cmake --build build
|
||||
- name: Test
|
||||
run: |
|
||||
ctest --test-dir build --rerun-failed --output-on-failure
|
||||
Artifacts:
|
||||
runs-on: ubuntu-latest
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install asciidoctor
|
||||
run: |
|
||||
sudo apt-get install asciidoctor
|
||||
asciidoctor doc/openmethod.adoc -o build_outputs_folder/index.html
|
||||
- name: Generate documentation
|
||||
run: |
|
||||
sudo apt-get install asciidoctor
|
||||
asciidoctor doc/openmethod.adoc -o build_outputs_folder/index.html
|
||||
- name: Build flat headers
|
||||
run: |
|
||||
mkdir -p build_outputs_folder/boost/openmethod
|
||||
python3 dev/flatten.py \
|
||||
build_outputs_folder/boost/openmethod.hpp \
|
||||
include/boost/openmethod.hpp \
|
||||
include/boost/openmethod/unique_ptr.hpp \
|
||||
include/boost/openmethod/shared_ptr.hpp \
|
||||
include/boost/openmethod/compiler.hpp
|
||||
python3 dev/flatten.py \
|
||||
build_outputs_folder/boost/openmethod/policies.hpp \
|
||||
include/boost/openmethod/policies.hpp
|
||||
- name: Upload static files as artifact
|
||||
uses: actions/upload-pages-artifact@v3 # or specific "vX.X.X" version tag for this action
|
||||
with:
|
||||
path: build_outputs_folder/
|
||||
- name: Deploy to GitHub Pages
|
||||
uses: actions/deploy-pages@v4
|
||||
15
.github/workflows/probe.yml
vendored
Normal file
15
.github/workflows/probe.yml
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
name: Probe Workflow
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
probe:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: List available compilers
|
||||
run: |
|
||||
lsb_release -a
|
||||
apt list --installed | grep clang
|
||||
apt list --installed | grep g++
|
||||
28
.gitignore
vendored
Normal file
28
.gitignore
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
.hrefs
|
||||
.rtags
|
||||
build/
|
||||
builds/
|
||||
**/#*#
|
||||
dependencies/*
|
||||
extern/*
|
||||
tests/benchmarks_parameters.hpp
|
||||
**/vcpkg_installed
|
||||
.venv/
|
||||
|
||||
build/*
|
||||
__build__/*
|
||||
|
||||
# ides
|
||||
.vscode/
|
||||
.vs/
|
||||
CMakeSettings.json
|
||||
|
||||
_deps/
|
||||
|
||||
export/
|
||||
|
||||
fetch_and_include/
|
||||
|
||||
tmpinst/
|
||||
|
||||
CMakeFiles/
|
||||
0
.gitmodules
vendored
Normal file
0
.gitmodules
vendored
Normal file
45
CMakeLists.txt
Normal file
45
CMakeLists.txt
Normal file
@@ -0,0 +1,45 @@
|
||||
# Copyright (c) 2018-2025 Jean-Louis Leroy
|
||||
# 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)
|
||||
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
if(POLICY CMP0167)
|
||||
cmake_policy(SET CMP0074 NEW)
|
||||
endif()
|
||||
|
||||
if(POLICY CMP0167)
|
||||
cmake_policy(SET CMP0167 NEW)
|
||||
endif()
|
||||
|
||||
project(boost_openmethod VERSION 1.87.0 LANGUAGES CXX)
|
||||
|
||||
if(NOT CMAKE_CXX_STANDARD)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
endif()
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
add_library(boost_openmethod INTERFACE)
|
||||
add_library(Boost::openmethod ALIAS boost_openmethod)
|
||||
|
||||
target_include_directories(boost_openmethod INTERFACE include)
|
||||
|
||||
find_package(Boost COMPONENTS)
|
||||
target_link_libraries(boost_openmethod INTERFACE Boost::boost)
|
||||
|
||||
if(MSVC)
|
||||
add_compile_options(/EHsc /FAs)
|
||||
endif()
|
||||
|
||||
if(BUILD_TESTING)
|
||||
message(STATUS "Building tests")
|
||||
include(CTest)
|
||||
enable_testing()
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
|
||||
if(BUILD_EXAMPLES)
|
||||
message(STATUS "Building examples")
|
||||
add_subdirectory(examples)
|
||||
endif()
|
||||
1
CODEOWNERS
Normal file
1
CODEOWNERS
Normal file
@@ -0,0 +1 @@
|
||||
* @jll63
|
||||
23
LICENSE
Normal file
23
LICENSE
Normal file
@@ -0,0 +1,23 @@
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
16
README.md
Normal file
16
README.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# Boost.OpenMethod
|
||||
|
||||
THIS IS NOT A BOOST LIBRARY (yet).
|
||||
|
||||
The content of this repository is derived from YOMM2. It has been adapted to
|
||||
Boost naming conventions for the purpose of being reviewed for inclusion in the
|
||||
Boost C++ libraries.
|
||||
|
||||
The documentation is [here](https://jll63.github.io/Boost.OpenMethod/).
|
||||
|
||||
You can experiment with the library on Compiler Explorer by including
|
||||
`<https://jll63.github.io/Boost.OpenMethod/boost/openmethod.hpp>`. It also
|
||||
includes the headers for the compiler, `shared_ptr` and `unique_ptr`. For
|
||||
example, here is the last iteration of the [AST
|
||||
example](https://godbolt.org/z/cPjzfanc8) from the tutorial. Don't forget to
|
||||
turn on optimizations (`-O2 -DNDEBUG`) and to select the Boost library.
|
||||
68
ce/2-method-vptr-final.cpp
Normal file
68
ce/2-method-vptr-final.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <boost/openmethod.hpp>
|
||||
#include <boost/openmethod/compiler.hpp>
|
||||
|
||||
struct Animal {
|
||||
const char* name;
|
||||
Animal(const char* name) : name(name) {
|
||||
}
|
||||
};
|
||||
|
||||
struct Dog : Animal {
|
||||
using Animal::Animal;
|
||||
};
|
||||
|
||||
struct Cat : Animal {
|
||||
using Animal::Animal;
|
||||
};
|
||||
|
||||
BOOST_OPENMETHOD_CLASSES(Animal, Dog, Cat);
|
||||
|
||||
using boost::openmethod::virtual_ptr;
|
||||
|
||||
BOOST_OPENMETHOD(
|
||||
meet, (virtual_ptr<Animal>, virtual_ptr<Animal>, std::ostream&), void);
|
||||
|
||||
BOOST_OPENMETHOD_OVERRIDE(
|
||||
meet, (virtual_ptr<Cat> a1, virtual_ptr<Cat> a2, std::ostream& os), void) {
|
||||
os << a1->name << " ignores " << a2->name << "\n";
|
||||
}
|
||||
|
||||
BOOST_OPENMETHOD_OVERRIDE(
|
||||
meet, (virtual_ptr<Dog> a1, virtual_ptr<Cat> a2, std::ostream& os), void) {
|
||||
os << a1->name << " chases " << a2->name << "\n";
|
||||
}
|
||||
|
||||
BOOST_OPENMETHOD_OVERRIDE(
|
||||
meet, (virtual_ptr<Cat> a1, virtual_ptr<Dog> a2, std::ostream& os), void) {
|
||||
os << a1->name << " runs away from " << a2->name << "\n";
|
||||
}
|
||||
|
||||
BOOST_OPENMETHOD_OVERRIDE(
|
||||
meet, (virtual_ptr<Dog> a1, virtual_ptr<Dog> a2, std::ostream& os), void) {
|
||||
os << a1->name << " wags tail at " << a2->name << "\n";
|
||||
}
|
||||
|
||||
void meet_animals(
|
||||
const std::vector<virtual_ptr<Animal>>& animals, std::ostream& os) {
|
||||
for (auto animal : animals) {
|
||||
for (auto other : animals) {
|
||||
if (&animal != &other) {
|
||||
meet(animal, other, os);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
boost::openmethod::initialize();
|
||||
|
||||
Dog hector{"Hector"}, snoopy{"Snoopy"};
|
||||
Cat felix{"Felix"}, sylvester{"Sylvester"};
|
||||
std::vector<virtual_ptr<Animal>> animals = {
|
||||
virtual_ptr<Dog>::final(hector), virtual_ptr<Cat>::final(felix),
|
||||
virtual_ptr<Cat>::final(sylvester), virtual_ptr<Dog>::final(snoopy)};
|
||||
|
||||
meet_animals(animals, std::cout);
|
||||
}
|
||||
69
ce/2-method-vptr.cpp
Normal file
69
ce/2-method-vptr.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <boost/openmethod.hpp>
|
||||
#include <boost/openmethod/compiler.hpp>
|
||||
|
||||
struct Animal {
|
||||
const char* name;
|
||||
Animal(const char* name) : name(name) {
|
||||
}
|
||||
virtual ~Animal() {
|
||||
}
|
||||
};
|
||||
|
||||
struct Dog : Animal {
|
||||
using Animal::Animal;
|
||||
};
|
||||
|
||||
struct Cat : Animal {
|
||||
using Animal::Animal;
|
||||
};
|
||||
|
||||
BOOST_OPENMETHOD_CLASSES(Animal, Dog, Cat);
|
||||
|
||||
using boost::openmethod::virtual_ptr;
|
||||
|
||||
BOOST_OPENMETHOD(
|
||||
meet, (virtual_ptr<Animal>, virtual_ptr<Animal>, std::ostream&), void);
|
||||
|
||||
BOOST_OPENMETHOD_OVERRIDE(
|
||||
meet, (virtual_ptr<Cat> a1, virtual_ptr<Cat> a2, std::ostream& os), void) {
|
||||
os << a1->name << " ignores " << a2->name << "\n";
|
||||
}
|
||||
|
||||
BOOST_OPENMETHOD_OVERRIDE(
|
||||
meet, (virtual_ptr<Dog> a1, virtual_ptr<Cat> a2, std::ostream& os), void) {
|
||||
os << a1->name << " chases " << a2->name << "\n";
|
||||
}
|
||||
|
||||
BOOST_OPENMETHOD_OVERRIDE(
|
||||
meet, (virtual_ptr<Cat> a1, virtual_ptr<Dog> a2, std::ostream& os), void) {
|
||||
os << a1->name << " runs away from " << a2->name << "\n";
|
||||
}
|
||||
|
||||
BOOST_OPENMETHOD_OVERRIDE(
|
||||
meet, (virtual_ptr<Dog> a1, virtual_ptr<Dog> a2, std::ostream& os), void) {
|
||||
os << a1->name << " wags tail at " << a2->name << "\n";
|
||||
}
|
||||
|
||||
void meet_animals(
|
||||
const std::vector<virtual_ptr<Animal>>& animals, std::ostream& os) {
|
||||
for (auto animal : animals) {
|
||||
for (auto other : animals) {
|
||||
if (&animal != &other) {
|
||||
meet(animal, other, os);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
boost::openmethod::initialize();
|
||||
|
||||
Dog hector{"Hector"}, snoopy{"Snoopy"};
|
||||
Cat felix{"Felix"}, sylvester{"Sylvester"};
|
||||
std::vector<virtual_ptr<Animal>> animals = {
|
||||
hector, felix, sylvester, snoopy};
|
||||
|
||||
meet_animals(animals, std::cout);
|
||||
}
|
||||
61
ce/2-method.cpp
Normal file
61
ce/2-method.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <boost/openmethod.hpp>
|
||||
#include <boost/openmethod/compiler.hpp>
|
||||
|
||||
struct Animal {
|
||||
const char* name;
|
||||
Animal(const char* name) : name(name) {
|
||||
}
|
||||
virtual ~Animal() {
|
||||
}
|
||||
};
|
||||
|
||||
struct Dog : Animal {
|
||||
using Animal::Animal;
|
||||
};
|
||||
|
||||
struct Cat : Animal {
|
||||
using Animal::Animal;
|
||||
};
|
||||
|
||||
BOOST_OPENMETHOD_CLASSES(Animal, Dog, Cat);
|
||||
|
||||
BOOST_OPENMETHOD(
|
||||
meet, (virtual_<Animal&>, virtual_<Animal&>, std::ostream&), void);
|
||||
|
||||
BOOST_OPENMETHOD_OVERRIDE(meet, (Cat & a1, Cat& a2, std::ostream& os), void) {
|
||||
os << a1.name << " ignores " << a2.name << "\n";
|
||||
}
|
||||
|
||||
BOOST_OPENMETHOD_OVERRIDE(meet, (Dog & a1, Cat& a2, std::ostream& os), void) {
|
||||
os << a1.name << " chases " << a2.name << "\n";
|
||||
}
|
||||
|
||||
BOOST_OPENMETHOD_OVERRIDE(meet, (Cat & a1, Dog& a2, std::ostream& os), void) {
|
||||
os << a1.name << " runs away from " << a2.name << "\n";
|
||||
}
|
||||
|
||||
BOOST_OPENMETHOD_OVERRIDE(meet, (Dog & a1, Dog& a2, std::ostream& os), void) {
|
||||
os << a1.name << " wags tail at " << a2.name << "\n";
|
||||
}
|
||||
|
||||
void meet_animals(const std::vector<Animal*>& animals, std::ostream& os) {
|
||||
for (auto animal : animals) {
|
||||
for (auto other : animals) {
|
||||
if (&animal != &other) {
|
||||
meet(*animal, *other, os);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
boost::openmethod::initialize();
|
||||
|
||||
Dog hector{"Hector"}, snoopy{"Snoopy"};
|
||||
Cat felix{"Felix"}, sylvester{"Sylvester"};
|
||||
std::vector<Animal*> animals = {&hector, &felix, &sylvester, &snoopy};
|
||||
|
||||
meet_animals(animals, std::cout);
|
||||
}
|
||||
28
ce/CMakeLists.txt
Normal file
28
ce/CMakeLists.txt
Normal file
@@ -0,0 +1,28 @@
|
||||
# Copyright (c) 2018-2024 Jean-Louis Leroy
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# See accompanying filce_e LICENSE_1_0.txt
|
||||
# or copy at hce_ttp://www.boost.oce_rg/LICENSE_1_0.txt)
|
||||
|
||||
add_executable(ce_virtual virtual.cpp)
|
||||
add_test(NAME ce_virtual COMMAND ce_virtual)
|
||||
|
||||
add_executable(ce_uni-method uni-method.cpp)
|
||||
add_test(NAME ce_uni-method COMMAND ce_uni-method)
|
||||
|
||||
add_executable(ce_uni-method-vptr uni-method-vptr.cpp)
|
||||
add_test(NAME ce_uni-method-vptr COMMAND ce_uni-method-vptr)
|
||||
|
||||
add_executable(ce_virtual-double virtual-double.cpp)
|
||||
add_test(NAME ce_virtual-double COMMAND ce_virtual-double)
|
||||
|
||||
add_executable(ce_2-method 2-method.cpp)
|
||||
add_test(NAME ce_2-method COMMAND ce_2-method)
|
||||
|
||||
add_executable(ce_2-method-vptr 2-method-vptr.cpp)
|
||||
add_test(NAME ce_2-method-vptr COMMAND ce_2-method-vptr)
|
||||
|
||||
add_executable(ce_2-method-vptr-final 2-method-vptr-final.cpp)
|
||||
add_test(NAME ce_2-method-vptr-fince_al COMMAND ce_2-method-vptr-final)
|
||||
|
||||
add_executable(ce_uni-method-vptr-final uni-method-vptr-final.cpp)
|
||||
add_test(NAME ce_uni-method-vptr-fce_inal COMMAND ce_uni-method-vptr-final)
|
||||
26
ce/README.md
Normal file
26
ce/README.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# YOMM2 on Compiler Explorer
|
||||
|
||||
YOMM2 is available on Compiler Explorer. Make sure that you also select Boost
|
||||
version 1.74 or above, and you probably want to add the `-O3 -DNDEBUG` compiler
|
||||
switches.
|
||||
|
||||
The following examples are available:
|
||||
|
||||
* The [examples](https://jll63.github.io/yomm2/ce/slides.html) from the slides.
|
||||
* The matrix example from the GitHub langing page.
|
||||
|
||||
The following examples use the diff mode to compare open methods with the
|
||||
equivalent (closed) virtual function based approaches.
|
||||
|
||||
* [virtual function call vs uni-method call via plain reference](https://jll63.github.io/yomm2/ce/vf-vs-1m-ref.html)
|
||||
* [virtual function call vs uni-method call via virtual_ptr ](https://jll63.github.io/yomm2/ce/vf-vs-1m-vptr.html)
|
||||
* [double dispatch vs multi-method call via plain reference](https://jll63.github.io/yomm2/ce/2d-vs-2m-ref.html)
|
||||
* [double dispatch vs multi-method call via virtual_ptr ](https://jll63.github.io/yomm2/ce/2d-vs-2m-vptr.html)
|
||||
|
||||
YOMM2 can also [add polymorphic operations to non-polymorphic
|
||||
classes](https://jll63.github.io/yomm2/ce/vptr-final.html).
|
||||
|
||||
When `virtual_ptr` is used in combination with generated static offsets, method
|
||||
dispatch matches the speed of virtual functions. It is also possible to generate
|
||||
dispatch data that can be installed without calling `update`, a fairly expensive
|
||||
operaiton. See [this example](https://jll63.github.io/yomm2/ce/generator.html).
|
||||
55
ce/uni-method-vptr-final.cpp
Normal file
55
ce/uni-method-vptr-final.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/openmethod.hpp>
|
||||
#include <boost/openmethod/compiler.hpp>
|
||||
|
||||
struct Animal {
|
||||
const char* name;
|
||||
Animal(const char* name) : name(name) {
|
||||
}
|
||||
};
|
||||
|
||||
struct Dog : Animal {
|
||||
using Animal::Animal;
|
||||
};
|
||||
|
||||
struct Cat : Animal {
|
||||
using Animal::Animal;
|
||||
};
|
||||
|
||||
BOOST_OPENMETHOD_CLASSES(Animal, Dog, Cat);
|
||||
|
||||
using boost::openmethod::final_virtual_ptr;
|
||||
using boost::openmethod::virtual_ptr;
|
||||
|
||||
BOOST_OPENMETHOD(poke, (virtual_ptr<Animal>, std::ostream&), void);
|
||||
|
||||
BOOST_OPENMETHOD_OVERRIDE(
|
||||
poke, (virtual_ptr<Cat> animal, std::ostream& os), void) {
|
||||
os << animal->name << " hisses.\n";
|
||||
}
|
||||
|
||||
BOOST_OPENMETHOD_OVERRIDE(
|
||||
poke, (virtual_ptr<Dog> animal, std::ostream& os), void) {
|
||||
os << animal->name << " barks.\n";
|
||||
}
|
||||
|
||||
void poke_animals(
|
||||
const std::vector<virtual_ptr<Animal>>& animals, std::ostream& os) {
|
||||
for (auto animal : animals) {
|
||||
poke(animal, os);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
boost::openmethod::initialize();
|
||||
|
||||
Dog hector{"Hector"}, snoopy{"Snoopy"};
|
||||
Cat felix{"Felix"}, sylvester{"Sylvester"};
|
||||
std::vector<virtual_ptr<Animal>> animals = {
|
||||
final_virtual_ptr(hector), virtual_ptr<Cat>::final(felix),
|
||||
final_virtual_ptr(sylvester), virtual_ptr<Dog>::final(snoopy)};
|
||||
|
||||
poke_animals(animals, std::cout);
|
||||
}
|
||||
54
ce/uni-method-vptr.cpp
Normal file
54
ce/uni-method-vptr.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <boost/openmethod.hpp>
|
||||
#include <boost/openmethod/compiler.hpp>
|
||||
|
||||
struct Animal {
|
||||
const char* name;
|
||||
Animal(const char* name) : name(name) {
|
||||
}
|
||||
virtual ~Animal() {
|
||||
}
|
||||
};
|
||||
|
||||
struct Dog : Animal {
|
||||
using Animal::Animal;
|
||||
};
|
||||
|
||||
struct Cat : Animal {
|
||||
using Animal::Animal;
|
||||
};
|
||||
|
||||
BOOST_OPENMETHOD_CLASSES(Animal, Dog, Cat);
|
||||
|
||||
using boost::openmethod::virtual_ptr;
|
||||
|
||||
BOOST_OPENMETHOD(poke, (virtual_ptr<Animal>, std::ostream&), void);
|
||||
|
||||
BOOST_OPENMETHOD_OVERRIDE(
|
||||
poke, (virtual_ptr<Cat> animal, std::ostream& os), void) {
|
||||
os << animal->name << " hisses.\n";
|
||||
}
|
||||
|
||||
BOOST_OPENMETHOD_OVERRIDE(
|
||||
poke, (virtual_ptr<Dog> animal, std::ostream& os), void) {
|
||||
os << animal->name << " barks.\n";
|
||||
}
|
||||
|
||||
void poke_animals(
|
||||
const std::vector<virtual_ptr<Animal>>& animals, std::ostream& os) {
|
||||
for (auto animal : animals) {
|
||||
poke(animal, os);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
boost::openmethod::initialize();
|
||||
|
||||
Dog hector{"Hector"}, snoopy{"Snoopy"};
|
||||
Cat felix{"Felix"}, sylvester{"Sylvester"};
|
||||
std::vector<virtual_ptr<Animal>> animals = {
|
||||
hector, felix, sylvester, snoopy};
|
||||
|
||||
poke_animals(animals, std::cout);
|
||||
}
|
||||
48
ce/uni-method.cpp
Normal file
48
ce/uni-method.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <boost/openmethod.hpp>
|
||||
#include <boost/openmethod/compiler.hpp>
|
||||
|
||||
struct Animal {
|
||||
const char* name;
|
||||
Animal(const char* name) : name(name) {
|
||||
}
|
||||
virtual ~Animal() {
|
||||
}
|
||||
};
|
||||
|
||||
struct Dog : Animal {
|
||||
using Animal::Animal;
|
||||
};
|
||||
|
||||
struct Cat : Animal {
|
||||
using Animal::Animal;
|
||||
};
|
||||
|
||||
BOOST_OPENMETHOD_CLASSES(Animal, Dog, Cat);
|
||||
|
||||
BOOST_OPENMETHOD(poke, (virtual_<Animal&>, std::ostream&), void);
|
||||
|
||||
BOOST_OPENMETHOD_OVERRIDE(poke, (Cat & animal, std::ostream& os), void) {
|
||||
os << animal.name << " hisses.\n";
|
||||
}
|
||||
|
||||
BOOST_OPENMETHOD_OVERRIDE(poke, (Dog & animal, std::ostream& os), void) {
|
||||
os << animal.name << " barks.\n";
|
||||
}
|
||||
|
||||
void poke_animals(const std::vector<Animal*>& animals, std::ostream& os) {
|
||||
for (auto animal : animals) {
|
||||
poke(*animal, os);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
boost::openmethod::initialize();
|
||||
|
||||
Dog hector{"Hector"}, snoopy{"Snoopy"};
|
||||
Cat felix{"Felix"}, sylvester{"Sylvester"};
|
||||
std::vector<Animal*> animals = {&hector, &felix, &sylvester, &snoopy};
|
||||
|
||||
poke_animals(animals, std::cout);
|
||||
}
|
||||
69
ce/virtual-double.cpp
Normal file
69
ce/virtual-double.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
struct Cat;
|
||||
struct Dog;
|
||||
|
||||
struct Animal {
|
||||
const char* name;
|
||||
Animal(const char* name) : name(name) {
|
||||
}
|
||||
virtual ~Animal() {
|
||||
}
|
||||
virtual void meet(Animal& other, std::ostream& os) = 0;
|
||||
virtual void meet_cat(Cat& other, std::ostream& os) = 0;
|
||||
virtual void meet_dog(Dog& other, std::ostream& os) = 0;
|
||||
};
|
||||
|
||||
struct Cat : Animal {
|
||||
using Animal::Animal;
|
||||
void meet(Animal& other, std::ostream& os) override;
|
||||
void meet_cat(Cat& other, std::ostream& os) override;
|
||||
void meet_dog(Dog& other, std::ostream& os) override;
|
||||
};
|
||||
|
||||
struct Dog : Animal {
|
||||
using Animal::Animal;
|
||||
void meet(Animal& other, std::ostream& os) override;
|
||||
void meet_cat(Cat& other, std::ostream& os) override;
|
||||
void meet_dog(Dog& other, std::ostream& os) override;
|
||||
};
|
||||
|
||||
void meet_animals(const std::vector<Animal*>& animals, std::ostream& os) {
|
||||
for (auto animal : animals) {
|
||||
for (auto other : animals) {
|
||||
if (animal != other) {
|
||||
animal->meet(*other, os);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
Dog hector{"Hector"}, snoopy{"Snoopy"};
|
||||
Cat felix{"Felix"}, sylvester{"Sylvester"};
|
||||
std::vector<Animal*> animals = {&hector, &felix, &sylvester, &snoopy};
|
||||
meet_animals(animals, std::cout);
|
||||
}
|
||||
|
||||
void Cat::meet(Animal& other, std::ostream& os) {
|
||||
other.meet_cat(*this, os);
|
||||
}
|
||||
|
||||
void Cat::meet_cat(Cat& other, std::ostream& os) {
|
||||
os << name << " ignores " << other.name << "\n";
|
||||
}
|
||||
|
||||
void Cat::meet_dog(Dog& other, std::ostream& os) {
|
||||
os << name << " runs away from " << other.name << "\n";
|
||||
}
|
||||
|
||||
void Dog::meet(Animal& other, std::ostream& os) {
|
||||
other.meet_dog(*this, os);
|
||||
}
|
||||
void Dog::meet_cat(Cat& other, std::ostream& os) {
|
||||
os << name << " chases " << other.name << "\n";
|
||||
}
|
||||
void Dog::meet_dog(Dog& other, std::ostream& os) {
|
||||
os << name << " wags tail at " << other.name << "\n";
|
||||
}
|
||||
38
ce/virtual.cpp
Normal file
38
ce/virtual.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
struct Animal {
|
||||
const char* name;
|
||||
Animal(const char* name) : name(name) {
|
||||
}
|
||||
virtual ~Animal() {
|
||||
}
|
||||
virtual void poke(std::ostream& os) = 0;
|
||||
};
|
||||
|
||||
struct Dog : Animal {
|
||||
using Animal::Animal;
|
||||
void poke(std::ostream& os) override {
|
||||
os << name << " barks.\n";
|
||||
}
|
||||
};
|
||||
|
||||
struct Cat : Animal {
|
||||
using Animal::Animal;
|
||||
void poke(std::ostream& os) override {
|
||||
os << name << " hisses.\n";
|
||||
}
|
||||
};
|
||||
|
||||
void poke_animals(const std::vector<Animal*>& animals, std::ostream& os) {
|
||||
for (auto animal : animals) {
|
||||
animal->poke(os);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
Dog hector{"Hector"}, snoopy{"Snoopy"};
|
||||
Cat felix{"Felix"}, sylvester{"Sylvester"};
|
||||
std::vector<Animal*> animals = {&hector, &felix, &sylvester, &snoopy};
|
||||
poke_animals(animals, std::cout);
|
||||
}
|
||||
137
clang-llvm
Normal file
137
clang-llvm
Normal file
@@ -0,0 +1,137 @@
|
||||
---
|
||||
Language: Cpp
|
||||
# BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -2
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveMacros: false
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: true
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllConstructorInitializersOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: MultiLine
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 80
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DeriveLineEnding: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: true
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
|
||||
Priority: 3
|
||||
SortPriority: 0
|
||||
- Regex: '.*'
|
||||
Priority: 1
|
||||
SortPriority: 0
|
||||
IncludeIsMainRegex: '(Test)?$'
|
||||
IncludeIsMainSourceRegex: ''
|
||||
IndentCaseLabels: false
|
||||
IndentGotoLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentWidth: 2
|
||||
IndentWrappedFunctionNames: false
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBinPackProtocolList: Auto
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PointerAlignment: Right
|
||||
ReflowComments: true
|
||||
SortIncludes: true
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyBlock: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInConditionalStatement: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
SpaceBeforeSquareBrackets: false
|
||||
Standard: Latest
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
TabWidth: 8
|
||||
UseCRLF: false
|
||||
UseTab: Never
|
||||
...
|
||||
|
||||
5
dev/ci-pre-configure-clang
Executable file
5
dev/ci-pre-configure-clang
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
wget https://apt.llvm.org/llvm.sh
|
||||
chmod +x llvm.sh
|
||||
sudo ./llvm.sh $1
|
||||
40
dev/flatten.py
Normal file
40
dev/flatten.py
Normal file
@@ -0,0 +1,40 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
import re
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('output', type=Path)
|
||||
parser.add_argument('input', nargs="+", type=Path)
|
||||
args = parser.parse_args()
|
||||
|
||||
prefix = args.input[0].absolute()
|
||||
|
||||
while prefix.name != 'boost':
|
||||
assert prefix.parent != prefix
|
||||
prefix = prefix.parent
|
||||
|
||||
prefix = prefix.parent
|
||||
skip = len(str(prefix)) + 1
|
||||
|
||||
def flatten(input, output, done):
|
||||
header = str(input)[skip:]
|
||||
if header in done:
|
||||
return
|
||||
done.add(header)
|
||||
with input.open() as ifh:
|
||||
for line in ifh:
|
||||
if m := re.match(r"#include <(boost/openmethod/[^>]+)>", line):
|
||||
include = m[1]
|
||||
print(file=output)
|
||||
flatten(prefix / include, output, done)
|
||||
print(file=output)
|
||||
else:
|
||||
output.write(line)
|
||||
|
||||
|
||||
with args.output.open('w') as ofh:
|
||||
done = set()
|
||||
for input in args.input:
|
||||
flatten(input.absolute(), ofh, done)
|
||||
8
dev/reformat
Executable file
8
dev/reformat
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
cd "$(dirname $0)/.."
|
||||
|
||||
srcs=$(find include examples test \
|
||||
-name '*.?pp' | grep -v cmake_fetchcontent | grep -v /CMakeFiles)
|
||||
|
||||
clang-format -i --verbose $srcs
|
||||
98
dev/v2-boost.py
Normal file
98
dev/v2-boost.py
Normal file
@@ -0,0 +1,98 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
import re
|
||||
from subprocess import check_call
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
BOOST_NAME = "openmethod"
|
||||
BOOST_INCLUDE = Path("include", "boost", BOOST_NAME)
|
||||
BOOST_OPENMETHOD_PATH = Path.home().joinpath("dev", "boost", "libs", BOOST_NAME)
|
||||
YOMM2_V2_PATH = Path.home().joinpath("dev", "yomm2")
|
||||
YOMM2_DIRS = "include/yorel/yomm2 tests examples ce".split()
|
||||
SKIP = [
|
||||
"cute",
|
||||
"keywords",
|
||||
"benchmark",
|
||||
"pss1",
|
||||
"lab",
|
||||
"manual_call",
|
||||
"generator",
|
||||
"containers",
|
||||
"conan",
|
||||
"vcpkg",
|
||||
"README",
|
||||
"cmakeyomm2",
|
||||
"templates",
|
||||
]
|
||||
REPLACE = (
|
||||
("YOREL_YOMM2_", f"BOOST_{BOOST_NAME.upper()}_"),
|
||||
("YOMM2_", f"BOOST_{BOOST_NAME.upper()}_"),
|
||||
("yOMM2_", f"BOOST_{BOOST_NAME.upper()}_DETAIL_"),
|
||||
("BOOST_OPENMETHOD_METHOD", "BOOST_OPENMETHOD"),
|
||||
("#include <yorel/yomm2/", f"#include <boost/{BOOST_NAME}/"),
|
||||
("<boost/openmethod/keywords.hpp>", "<boost/openmethod.hpp>"),
|
||||
("yorel", "boost"),
|
||||
("yomm2", "openmethod"),
|
||||
("YOMM2_DECLARE|declare_method", "BOOST_OPENMETHOD"),
|
||||
("YOMM2_DEFINE|define_method", "BOOST_OPENMETHOD_OVERRIDE"),
|
||||
("YOMM2_CLASS(ES)?|register_class(es)?", "BOOST_OPENMETHOD_CLASSES"),
|
||||
)
|
||||
|
||||
git = f"git diff --name-only -- boost test examples"
|
||||
print(git)
|
||||
|
||||
modified = subprocess.check_output(git.split(), encoding="ascii")
|
||||
|
||||
if modified:
|
||||
sys.exit("Unstaged changes:\n" + modified)
|
||||
|
||||
git = f"git -C {YOMM2_V2_PATH} rev-parse --abbrev-ref HEAD"
|
||||
print(git)
|
||||
|
||||
version = subprocess.check_output(git.split(), encoding="ascii").strip()
|
||||
|
||||
if version != "v2":
|
||||
sys.exit(f"Source directory is at version {version}, v2 is required.\n")
|
||||
|
||||
|
||||
def skip(path):
|
||||
for skip in SKIP:
|
||||
if skip in str(path):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
for dir in YOMM2_DIRS:
|
||||
for from_path in (YOMM2_V2_PATH / dir).rglob("*.?pp"):
|
||||
if skip(from_path):
|
||||
continue
|
||||
|
||||
with from_path.open() as f:
|
||||
content = f.read()
|
||||
|
||||
content = re.sub(r'#include "(yorel/yomm2/[^"])+"', r"#include <\1>", content)
|
||||
|
||||
for replace in REPLACE:
|
||||
content = re.sub(*replace, content)
|
||||
|
||||
to_path = Path(
|
||||
str(from_path)
|
||||
.replace(str(YOMM2_V2_PATH), str(BOOST_OPENMETHOD_PATH))
|
||||
.replace("yorel/yomm2", f"boost/{BOOST_NAME}")
|
||||
.replace("tests/", "test/")
|
||||
)
|
||||
|
||||
print(f"{from_path} -> {to_path}...")
|
||||
|
||||
to_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
with to_path.open("w") as f:
|
||||
f.write(content)
|
||||
|
||||
check_call(["clang-format", "-i", str(to_path)])
|
||||
|
||||
print("done")
|
||||
39
dev/yomm2filt
Executable file
39
dev/yomm2filt
Executable file
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import fileinput
|
||||
import re
|
||||
from subprocess import Popen, PIPE
|
||||
import threading
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("-s", "--scope", help="do not simplify scopes")
|
||||
parser.add_argument("-y", "--prefix", help="do not remove YOMM2 prefixes")
|
||||
parser.add_argument("-p", "--policy", help="do not remove policy")
|
||||
parser.add_argument("files", nargs="*", default=("-"))
|
||||
args = parser.parse_args()
|
||||
|
||||
def process(fh):
|
||||
while True:
|
||||
line = fh.readline()
|
||||
if not line:
|
||||
return
|
||||
if not args.prefix:
|
||||
line = re.sub(r"\s*,\s*yorel::yomm2::policy::\w+", "", line)
|
||||
if not args.scope:
|
||||
line = re.sub(r"(\w+::)+", "", line)
|
||||
if not args.prefix:
|
||||
line = re.sub(r"YoMm2_S_", "", line)
|
||||
print(line, end="")
|
||||
|
||||
i = 0
|
||||
|
||||
with Popen(
|
||||
"/usr/bin/c++filt --types".split(), stdin=PIPE, stdout=PIPE, encoding="ascii"
|
||||
) as cppfilt:
|
||||
demangler = threading.Thread(target=process, args=[cppfilt.stdout])
|
||||
demangler.start()
|
||||
for line in fileinput.input(files=args.files):
|
||||
print(line, file=cppfilt.stdin, end="")
|
||||
cppfilt.stdin.close()
|
||||
demangler.join()
|
||||
43
doc/BOOST_OPENMETHOD.adoc
Normal file
43
doc/BOOST_OPENMETHOD.adoc
Normal file
@@ -0,0 +1,43 @@
|
||||
|
||||
[#BOOST_OPENMETHOD]
|
||||
|
||||
## BOOST_OPENMETHOD
|
||||
|
||||
### Synopsis
|
||||
|
||||
Defined in <boost/openmethod/macros.hpp>.
|
||||
|
||||
```c++
|
||||
BOOST_OPENMETHOD(NAME, (PARAMETERS...), RETURN_TYPE [, POLICY]);
|
||||
```
|
||||
|
||||
### Description
|
||||
|
||||
Declares a method.
|
||||
|
||||
### Effects
|
||||
|
||||
The macro expands to several constructs:
|
||||
|
||||
* A `struct` forward declaration that acts as the method's identifier:
|
||||
|
||||
```c++
|
||||
struct BOOST_OPENMETHOD_NAME(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_NAME(NAME)(PARAMETERS...), RETURN_TYPE, POLICY>::fn`.
|
||||
|
||||
* A guide function used to match overriders with the method:
|
||||
|
||||
```c++
|
||||
auto BOOST_OPENMETHOD_NAME(NAME)_guide(...)
|
||||
-> ::boost::openmethod::method<
|
||||
BOOST_OPENMETHOD_NAME(NAME)(PARAMETERS...), RETURN_TYPE [, POLICY]>;
|
||||
```
|
||||
|
||||
NOTE: The default value for `POLICY` is the value of
|
||||
`BOOST_OPENMETHOD_DEFAULT_POLICY` at the point `<boost/openmethod/core.hpp>` is
|
||||
included. Changing the value of this symbol has no effect after that point.
|
||||
23
doc/BOOST_OPENMETHOD_CLASSES.adoc
Normal file
23
doc/BOOST_OPENMETHOD_CLASSES.adoc
Normal file
@@ -0,0 +1,23 @@
|
||||
|
||||
[#BOOST_OPENMETHOD_CLASSES]
|
||||
|
||||
## BOOST_OPENMETHOD_CLASSES
|
||||
|
||||
### Synopsis
|
||||
|
||||
Defined in <boost/openmethod/macros.hpp>.
|
||||
|
||||
```c++
|
||||
BOOST_OPENMETHOD_CLASSES(CLASSES...[, POLICY]);
|
||||
```
|
||||
|
||||
### Description
|
||||
|
||||
Register `CLASSES` in POLICY.
|
||||
|
||||
NOTE: The default value for `POLICY` is the value of
|
||||
`BOOST_OPENMETHOD_DEFAULT_POLICY` 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.
|
||||
22
doc/BOOST_OPENMETHOD_DEFAULT_POLICY.adoc
Normal file
22
doc/BOOST_OPENMETHOD_DEFAULT_POLICY.adoc
Normal file
@@ -0,0 +1,22 @@
|
||||
|
||||
[#BOOST_OPENMETHOD_DEFAULT_POLICY]
|
||||
|
||||
## BOOST_OPENMETHOD_DEFAULT_POLICY
|
||||
|
||||
### Description
|
||||
|
||||
The name of the default policy.
|
||||
|
||||
`BOOST_OPENMETHOD_DEFAULT_POLICY` 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_policy` is used.
|
||||
|
||||
`BOOST_OPENMETHOD_DEFAULT_POLICY` 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. Create a policy class, and set `BOOST_OPENMETHOD_DEFAULT_POLICY`.
|
||||
3. Include `<boost/openmethod/core.hpp>`.
|
||||
19
doc/BOOST_OPENMETHOD_INLINE_OVERRIDE.adoc
Normal file
19
doc/BOOST_OPENMETHOD_INLINE_OVERRIDE.adoc
Normal file
@@ -0,0 +1,19 @@
|
||||
|
||||
[#BOOST_OPENMETHOD_INLINE_OVERRIDE]
|
||||
|
||||
## BOOST_OPENMETHOD_INLINE_OVERRIDE
|
||||
|
||||
### Synopsis
|
||||
|
||||
Defined in <boost/openmethod/macros.hpp>.
|
||||
|
||||
```c++
|
||||
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.
|
||||
17
doc/BOOST_OPENMETHOD_NAME.adoc
Normal file
17
doc/BOOST_OPENMETHOD_NAME.adoc
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
[#BOOST_OPENMETHOD_NAME]
|
||||
|
||||
## BOOST_OPENMETHOD_NAME
|
||||
|
||||
### Synopsis
|
||||
|
||||
Defined in <boost/openmethod/macros/name.hpp>.
|
||||
|
||||
```c++
|
||||
#define BOOST_OPENMETHOD_NAME(NAME) boost_openmethod_#NAME
|
||||
```
|
||||
|
||||
### Description
|
||||
|
||||
Generate a long name from a short name, hopefully avoiding conflicts with
|
||||
user-defined names.
|
||||
59
doc/BOOST_OPENMETHOD_OVERRIDE.adoc
Normal file
59
doc/BOOST_OPENMETHOD_OVERRIDE.adoc
Normal file
@@ -0,0 +1,59 @@
|
||||
|
||||
[#BOOST_OPENMETHOD_OVERRIDE]
|
||||
|
||||
## BOOST_OPENMETHOD_OVERRIDE
|
||||
|
||||
### Synopsis
|
||||
|
||||
Defined in <boost/openmethod/macros.hpp>.
|
||||
|
||||
```c++
|
||||
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`:
|
||||
|
||||
```c++
|
||||
template<typename...> BOOST_OPENMETHOD_OVERRIDERS(NAME);
|
||||
```
|
||||
|
||||
* A specialization of the container template for the overrider:
|
||||
|
||||
```c++
|
||||
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:
|
||||
|
||||
```c++
|
||||
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.
|
||||
16
doc/BOOST_OPENMETHOD_OVERRIDERS.adoc
Normal file
16
doc/BOOST_OPENMETHOD_OVERRIDERS.adoc
Normal file
@@ -0,0 +1,16 @@
|
||||
|
||||
## BOOST_OPENMETHOD_OVERRIDERS
|
||||
|
||||
### Synopsis
|
||||
|
||||
Defined in <boost/openmethod/macros.hpp>.
|
||||
|
||||
```c++
|
||||
#define BOOST_OPENMETHOD_OVERRIDERS(NAME) \
|
||||
BOOST_PP_CAT(BOOST_OPENMETHOD_NAME(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.
|
||||
16
doc/BOOST_OPENMETHOD_REGISTER.adoc
Normal file
16
doc/BOOST_OPENMETHOD_REGISTER.adoc
Normal file
@@ -0,0 +1,16 @@
|
||||
|
||||
[#BOOST_OPENMETHOD_REGISTER]
|
||||
|
||||
## BOOST_OPENMETHOD_REGISTER
|
||||
|
||||
### Synopsis
|
||||
|
||||
Defined in <boost/openmethod/macros/register.hpp>.
|
||||
|
||||
```c++
|
||||
BOOST_OPENMETHOD_REGISTER(TYPE);
|
||||
```
|
||||
|
||||
### Description
|
||||
|
||||
Creates a static instance of `TYPE`, using a unique generated name.
|
||||
19
doc/Jamfile
Normal file
19
doc/Jamfile
Normal file
@@ -0,0 +1,19 @@
|
||||
# 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 : <asciidoctor-attribute>stylesheet=zajo-dark.css <asciidoctor-attribute>linkcss ;
|
||||
install html_ : index.html skin.png zajo-dark.css zajo-light.css rouge-github.css : <location>html ;
|
||||
|
||||
# pdf openmethod.pdf : openmethod.adoc : <asciidoctor-doctype>book <asciidoctor-attribute>pdf-themesdir=. <asciidoctor-attribute>pdf-theme=openmethod ;
|
||||
# install pdf_ : openmethod.pdf : <location>html ;
|
||||
|
||||
alias boostdoc ;
|
||||
explicit boostdoc ;
|
||||
alias boostrelease : html_ ;
|
||||
explicit boostrelease ;
|
||||
18
doc/abstract_policy.adoc
Normal file
18
doc/abstract_policy.adoc
Normal file
@@ -0,0 +1,18 @@
|
||||
## abstract_policy
|
||||
|
||||
### Synopsis
|
||||
|
||||
Defined in <boost/openmethod/policies/basic_policy.hpp>.
|
||||
|
||||
```c++
|
||||
namespace boost::openmethod::policies {
|
||||
|
||||
struct abstract_policy {};
|
||||
|
||||
}
|
||||
```
|
||||
### Description
|
||||
|
||||
`abstract_policy` is a required base class for a policy. It makes it possible
|
||||
for meta-functions such as `use_classes` to discriminate between user classes
|
||||
and the (optional) policy class.
|
||||
34
doc/basic_error_output.adoc
Normal file
34
doc/basic_error_output.adoc
Normal file
@@ -0,0 +1,34 @@
|
||||
|
||||
## basic_error_output
|
||||
|
||||
### Synopsis
|
||||
|
||||
Defined in <boost/openmethod/policies/basic_error_output.hpp>.
|
||||
|
||||
```c++
|
||||
namespace boost::openmethod::policies {
|
||||
|
||||
template<class Policy, typename Stream = /*unspecified*/>
|
||||
struct basic_error_output : virtual error_output {
|
||||
static Stream error_stream;
|
||||
};
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
### Description
|
||||
|
||||
`basic_error_output` is an implementation of `error_output` that writes error
|
||||
messages to a `RestrictedOutputStream`.
|
||||
|
||||
### Members
|
||||
|
||||
#### error_stream
|
||||
|
||||
```c++
|
||||
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.
|
||||
144
doc/basic_policy.adoc
Normal file
144
doc/basic_policy.adoc
Normal file
@@ -0,0 +1,144 @@
|
||||
|
||||
## basic_policy
|
||||
|
||||
### Synopsis
|
||||
|
||||
Defined in <boost/openmethod/policies/basic_policy.hpp>.
|
||||
|
||||
```c++
|
||||
namespace boost::openmethod {
|
||||
|
||||
namespace policies {
|
||||
|
||||
template<class Policy, class... Facets>
|
||||
struct basic_policy : virtual abstract_policy,
|
||||
virtual domain<Policy>,
|
||||
virtual Facets... {
|
||||
template<class Facet>
|
||||
static constexpr bool has_facet = /*unspecified*/;
|
||||
|
||||
template<class NewPolicy>
|
||||
using fork = /*unspecified*/;
|
||||
|
||||
template<class... MoreFacets>
|
||||
using add = /*unspecified*/;
|
||||
|
||||
template<class Base, class Facet>
|
||||
using replace = /*unspecified*/;
|
||||
|
||||
template<class Base>
|
||||
using remove = /*unspecified*/;
|
||||
};
|
||||
|
||||
struct release : basic_policy<release, ...> {};
|
||||
|
||||
struct debug : release::add<...> {};
|
||||
|
||||
} // policies
|
||||
|
||||
#ifdef NDEBUG
|
||||
using default_policy = policies::release;
|
||||
#else
|
||||
using default_policy = policies::debug;
|
||||
#endif
|
||||
|
||||
} // boost::openmethod
|
||||
```
|
||||
|
||||
### Description
|
||||
|
||||
`basic_policy` implements a policy, which consists of a a collection of methods,
|
||||
classes, dispatch data, and facets, 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.
|
||||
|
||||
Some of these functionalities require static variables local to the policy.
|
||||
Forthis reason, `basic_policy` uses the CRTP pattern to provide ensure that two
|
||||
different policies - and the facets they contain - get their own copies of the
|
||||
static state.
|
||||
|
||||
### Members
|
||||
|
||||
#### has_facet
|
||||
|
||||
```c++
|
||||
template<class Facet>
|
||||
static constexpr bool has_facet;
|
||||
```
|
||||
|
||||
Evaluates to `true` if _Policy_ contains _Facet_.
|
||||
|
||||
#### fork
|
||||
|
||||
```c++
|
||||
template<class NewPolicy>
|
||||
using fork;
|
||||
```
|
||||
|
||||
Creates a new policy from an existing one. _NewPolicy_, and the facets it
|
||||
contains, do 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.
|
||||
|
||||
#### add
|
||||
|
||||
```c++
|
||||
template<class... MoreFacets>
|
||||
using add;
|
||||
```
|
||||
|
||||
Creates a new policy by adding _MoreFacets_ to the original policy's collection
|
||||
of facets. The original policy and the new one share static variables.
|
||||
|
||||
#### replace
|
||||
|
||||
```c++
|
||||
template<class Base, class NewFacet>
|
||||
using replace;
|
||||
```
|
||||
|
||||
Creates a new policy by replacing the facet in _Policy_ that derives from _Base_
|
||||
with _NewFacet_. It is not an error if _policy_ does not contain such a facet;
|
||||
in that case, the new policy contains the same facet as the original one.
|
||||
|
||||
The original policy and the new one share static variables.
|
||||
|
||||
#### remove
|
||||
|
||||
```c++
|
||||
template<class Base>
|
||||
using remove;
|
||||
```
|
||||
|
||||
Creates a new policy by removing the facet in _Policy_ that derives from _Base_.
|
||||
It is not an error if _policy_ does not contain such a facet; in that case, the
|
||||
new policy contains the same facet as the original one.
|
||||
|
||||
The original policy and the new one share static variables.
|
||||
|
||||
### Non-members
|
||||
|
||||
#### release
|
||||
|
||||
```c++
|
||||
struct release;
|
||||
```
|
||||
|
||||
A policy that contains facet implementations `std_rtti`, `fast_perfect_hash`,
|
||||
`vptr_vector` and `vectored_error_handler`.
|
||||
|
||||
#### debug
|
||||
|
||||
```c++
|
||||
struct debug;
|
||||
```
|
||||
|
||||
The `release` policy with additional facet 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_policy
|
||||
|
||||
An alias for `release` if `NDEBUG` is defined, and for `debug` otherwise.
|
||||
43
doc/basic_trace_output.adoc
Normal file
43
doc/basic_trace_output.adoc
Normal file
@@ -0,0 +1,43 @@
|
||||
|
||||
## basic_trace_output
|
||||
|
||||
### Synopsis
|
||||
|
||||
Defined in <boost/openmethod/policies/basic_trace_output.hpp>.
|
||||
|
||||
```c++
|
||||
namespace boost::openmethod::policies {
|
||||
|
||||
template<class Policy, typename Stream = /*unspecified*/>
|
||||
struct basic_trace_output : virtual trace_output {
|
||||
static bool trace_enabled;
|
||||
static Stream trace_stream;
|
||||
};
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
### Description
|
||||
|
||||
`basic_error_output` is an implementation of `trace_output` that writes error
|
||||
messages to a `RestrictedOutputStream`.
|
||||
|
||||
### Members
|
||||
|
||||
#### trace_enabled
|
||||
|
||||
```c++
|
||||
static bool trace_enabled;
|
||||
```
|
||||
|
||||
Set to `true` if environment variable `BOOST_OPENMETHOD_TRACE` is set to `1`.
|
||||
|
||||
#### trace_stream
|
||||
|
||||
```c++
|
||||
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.
|
||||
92
doc/core_api.adoc
Normal file
92
doc/core_api.adoc
Normal file
@@ -0,0 +1,92 @@
|
||||
|
||||
## 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:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
#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:
|
||||
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
include::{examplesdir}/core_api.cpp[tag=method]
|
||||
----
|
||||
|
||||
NOTE: BOOST_OPENMETHOD and associated macros use `BOOST_OPENMETHOD_NAME` in
|
||||
their implementation. This makes it possible to mix the "macro" and "core"
|
||||
styles.
|
||||
|
||||
We call the method via the nested function object `fn`:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
poke::fn(std::cout, animal);
|
||||
----
|
||||
|
||||
Overriders are ordinary functions, added to a method using the nested template
|
||||
`override`:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
include::{examplesdir}/core_api.cpp[tag=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:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
include::{examplesdir}/core_api.cpp[tag=poke_dog]
|
||||
----
|
||||
|
||||
`next` is available from the method's nested `next` template:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
include::{examplesdir}/core_api.cpp[tag=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`:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
include::{examplesdir}/core_api.cpp[tag=use_classes]
|
||||
----
|
||||
|
||||
Finally, we call the method via the static member of the method class `fn`:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
include::{examplesdir}/core_api.cpp[tag=main]
|
||||
----
|
||||
163
doc/custom_rtti.adoc
Normal file
163
doc/custom_rtti.adoc
Normal file
@@ -0,0 +1,163 @@
|
||||
|
||||
## Custom RTTI
|
||||
|
||||
Stock policies use the `std_rtti` implementation of `rtti`. Here is its full
|
||||
source:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
struct std_rtti : rtti {
|
||||
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);
|
||||
}
|
||||
};
|
||||
----
|
||||
|
||||
* `static_type` is used by class registration, by `virtual_ptr`{empty}'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:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
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 facet. We must _not_ include
|
||||
`<boost/openmethod/core.hpp>` or any header that includes it yet.
|
||||
|
||||
Here is the facet implementation:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
include::{examplesdir}/custom_rtti.cpp[tag=facet]
|
||||
----
|
||||
|
||||
This facet 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:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
include::{examplesdir}/custom_rtti.cpp[tag=policy]
|
||||
----
|
||||
|
||||
Now we can include the "core" header and write the example:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
include::{examplesdir}/custom_rtti.cpp[tag=example]
|
||||
----
|
||||
|
||||
This programs compiles 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` facet 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:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
include::{examplesdir}/deferred_custom_rtti.cpp[tag=classes]
|
||||
// ditto for Dog
|
||||
----
|
||||
|
||||
The rtti facet is the same, with one more function:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
struct custom_rtti : bom::policies::rtti {
|
||||
// as before
|
||||
|
||||
include::{examplesdir}/deferred_custom_rtti.cpp[tag=dynamic_cast_ref]
|
||||
};
|
||||
----
|
||||
|
||||
Finally, the policy contains an additional facet - `deferred_static_rtti`:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
struct custom_policy
|
||||
: bom::policies::basic_policy<
|
||||
custom_policy, custom_rtti,
|
||||
bom::policies::deferred_static_rtti, // <-- additional facet
|
||||
bom::policies::vptr_vector<custom_policy>> {};
|
||||
----
|
||||
|
||||
The example is the same as in the previous section.
|
||||
25
doc/deferred_static_rtti.adoc
Normal file
25
doc/deferred_static_rtti.adoc
Normal file
@@ -0,0 +1,25 @@
|
||||
|
||||
## deferred_static_rtti
|
||||
|
||||
### Synopsis
|
||||
|
||||
Defined in <boost/openmethod/policies/basic_policy.hpp>.
|
||||
|
||||
```c++
|
||||
namespace boost::openmethod::policies {
|
||||
|
||||
struct deferred_static_rtti : virtual rtti {};
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
### Description
|
||||
|
||||
`deferred_static_rtti` is a facet 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` facet in the
|
||||
process. This can result in collecting the type ids _before_ they have been
|
||||
initialized. Adding this facet to a policy moves the collection of type ids to
|
||||
`initialize`.
|
||||
12
doc/docinfo.html
Normal file
12
doc/docinfo.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<meta name="keywords" content="c++,error handling,open source">
|
||||
<meta name="description" content="Lightweight Error Augmentation Framework">
|
||||
<link rel="stylesheet" href="./zajo-light.css" disabled=true>
|
||||
<script>
|
||||
function switch_style()
|
||||
{
|
||||
var i, tag;
|
||||
for( i=0, tag=document.getElementsByTagName("link"); i<tag.length; i++ )
|
||||
if( tag[i].rel.indexOf("stylesheet")!=-1 && tag[i].href.includes("zajo-") )
|
||||
tag[i].disabled = !tag[i].disabled;
|
||||
}
|
||||
</script>
|
||||
34
doc/domain.adoc
Normal file
34
doc/domain.adoc
Normal file
@@ -0,0 +1,34 @@
|
||||
|
||||
## domain
|
||||
|
||||
### Synopsis
|
||||
|
||||
Defined in <boost/openmethod/policies/basic_policy.hpp>.
|
||||
|
||||
```c++
|
||||
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
|
||||
|
||||
```c++
|
||||
template<class Class>
|
||||
static vptr_type static_vptr;
|
||||
```
|
||||
|
||||
Contains the pointer to the v-table for _Class_. Set by `initialize`.
|
||||
63
doc/error_handler.adoc
Normal file
63
doc/error_handler.adoc
Normal file
@@ -0,0 +1,63 @@
|
||||
|
||||
## error_handler
|
||||
|
||||
### Synopsis
|
||||
|
||||
Defined in <boost/openmethod/policies/basic_policy.hpp>.
|
||||
|
||||
```c++
|
||||
namespace boost::openmethod::policies {
|
||||
|
||||
struct error_handler;
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Defined in <boost/openmethod/types.hpp>.
|
||||
|
||||
```c++
|
||||
namespace boost::openmethod {
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
} // boost::openmethod::policies
|
||||
```
|
||||
|
||||
### Description
|
||||
|
||||
`error_handler` is a facet 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 facet 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
|
||||
|
||||
```c++
|
||||
| static auto error(const T&) -> void;
|
||||
```
|
||||
55
doc/error_handling.adoc
Normal file
55
doc/error_handling.adoc
Normal file
@@ -0,0 +1,55 @@
|
||||
|
||||
## Error Handling
|
||||
|
||||
When an error is encountered, the program is terminated by a call to `abort`. If
|
||||
the policy contains an `error_handler` facet, 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 facet with
|
||||
`vectored_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`:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
include::{examplesdir}/vectored_error_handler.cpp[tag=example]
|
||||
----
|
||||
|
||||
Output:
|
||||
|
||||
[source,console]
|
||||
----
|
||||
spin
|
||||
not implemented
|
||||
spin
|
||||
----
|
||||
|
||||
We can also replace the `error_handler` facet with our own. For example:
|
||||
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
include::{examplesdir}/throw_error_handler.cpp[tag=example]
|
||||
----
|
||||
|
||||
[source,console]
|
||||
----
|
||||
spin
|
||||
not implemented
|
||||
spin
|
||||
----
|
||||
|
||||
Stock facet `throw_error_handler` does this for all the exception types:
|
||||
|
||||
```c++
|
||||
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
|
||||
```
|
||||
28
doc/error_output.adoc
Normal file
28
doc/error_output.adoc
Normal file
@@ -0,0 +1,28 @@
|
||||
|
||||
## error_output
|
||||
|
||||
### Synopsis
|
||||
|
||||
Defined in <boost/openmethod/policies/basic_policy.hpp>.
|
||||
|
||||
```c++
|
||||
namespace boost::openmethod::policies {
|
||||
|
||||
struct error_output {};
|
||||
|
||||
} // boost::openmethod::policies
|
||||
```
|
||||
|
||||
### Description
|
||||
|
||||
`error_output` is a facet that provides a stream for writing error messages.
|
||||
|
||||
### Requirements
|
||||
|
||||
#### error_stream
|
||||
|
||||
```c++
|
||||
static RestrictedOutputStream error_stream;
|
||||
```
|
||||
|
||||
A static variable that satisfies the requirements of `RestrictedOutputStream`.
|
||||
39
doc/friendship.adoc
Normal file
39
doc/friendship.adoc
Normal file
@@ -0,0 +1,39 @@
|
||||
|
||||
## Friendship
|
||||
|
||||
Overriders are implemented as static functions located in specializations of a
|
||||
template named after the method, declared in the same scope. Macro
|
||||
`BOOST_OPENMETHOD_OVERRIDERS` returns that name. The template argument for a
|
||||
specialization is the signature of the overrider. For example, the overrider of
|
||||
`poke` for `Cat` is:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
BOOST_OPENMETHOD_OVERRIDERS(poke)<
|
||||
void(std::ostream& os, virtual_ptr<Cat> cat)>::fn;
|
||||
----
|
||||
|
||||
We can thus grant friendship to all the overriders of `poke`:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
include::{examplesdir}/friendship.cpp[tag=friend_all]
|
||||
----
|
||||
|
||||
Be aware, though, that the overriders of _any_ method called `poke` - even with
|
||||
a different signature - are granted friendship.
|
||||
|
||||
We can also grant friendship to individual overriders:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
include::{examplesdir}/friendship.cpp[tag=friend]
|
||||
----
|
||||
|
||||
// If the overriders exist in a different namespace, we must take into account that
|
||||
// the overriders template is declared in the current namespace.
|
||||
|
||||
// [source,c++]
|
||||
// ----
|
||||
// include::{examplesdir}/friendship_across_namespaces.cpp[tag=friend]
|
||||
// ----
|
||||
37
doc/headers.adoc
Normal file
37
doc/headers.adoc
Normal file
@@ -0,0 +1,37 @@
|
||||
### <boost/openmethod.hpp>
|
||||
|
||||
### <boost/openmethod/core.hpp>
|
||||
|
||||
### <boost/openmethod/shared_ptr.hpp>
|
||||
|
||||
### <boost/openmethod/unique_ptr.hpp>
|
||||
|
||||
### <boost/openmethod/compiler.hpp>
|
||||
|
||||
### <boost/openmethod/policies.hpp>
|
||||
|
||||
### <boost/openmethod/macros.hpp>
|
||||
|
||||
### <boost/openmethod/macros/register.hpp>
|
||||
|
||||
### <boost/openmethod/macros/name.hpp>
|
||||
|
||||
### <boost/openmethod/policies/basic_policy.hpp>
|
||||
|
||||
### <boost/openmethod/policies/vectored_error_handler.hpp>
|
||||
|
||||
### <boost/openmethod/policies/std_rtti.hpp>
|
||||
|
||||
### <boost/openmethod/policies/basic_trace_output.hpp>
|
||||
|
||||
### <boost/openmethod/policies/basic_error_output.hpp>
|
||||
|
||||
### <boost/openmethod/policies/basic_indirect_vptr.hpp>
|
||||
|
||||
### <boost/openmethod/policies/vptr_map.hpp>
|
||||
|
||||
### <boost/openmethod/policies/fast_perfect_hash.hpp>
|
||||
|
||||
### <boost/openmethod/policies/vptr_vector.hpp>
|
||||
|
||||
### <boost/openmethod/policies/throw_error.hpp>
|
||||
103
doc/hello_world.adoc
Normal file
103
doc/hello_world.adoc
Normal file
@@ -0,0 +1,103 @@
|
||||
|
||||
## Hello World
|
||||
|
||||
Consider the following program, intended to demonstrate the basics of virtual
|
||||
functions:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
include::{examplesdir}/virtual_func.cpp[tag=code]
|
||||
----
|
||||
|
||||
We are going to rewrite this using open-methods.
|
||||
|
||||
First we remove the `poke` virtual functions from the domain classes:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
include::{examplesdir}/hello_world.cpp[tag=domain_classes]
|
||||
----
|
||||
|
||||
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.
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
include::{examplesdir}/hello_world.cpp[tag=method]
|
||||
----
|
||||
|
||||
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`:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
include::{examplesdir}/hello_world.cpp[tag=overriders]
|
||||
----
|
||||
|
||||
`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.
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
include::{examplesdir}/hello_world.cpp[tag=next]
|
||||
----
|
||||
|
||||
All classes involved in open-method calls need to be registered using the
|
||||
`BOOST_OPENMETHOD_CLASSES` macro:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
include::{examplesdir}/hello_world.cpp[tag=classes]
|
||||
----
|
||||
|
||||
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:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
// 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`:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
include::{examplesdir}/hello_world.cpp[tag=main,indent=0]
|
||||
----
|
||||
|
||||
We call `poke` like any ordinary function. We can pass it the animals by
|
||||
reference, because `virtual_ptr` has a conversion constructor for that:
|
||||
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
include::{examplesdir}/hello_world.cpp[tag=call]
|
||||
----
|
||||
|
||||
NOTE: `virtual_ptr` is more like a reference than a pointer: it cannot be null,
|
||||
and it cannot be re-assigned. The only reason why it is not called `virtual_ref`
|
||||
is to save the name in case it becomes possible to overload the dot operator in
|
||||
future versions of C++.
|
||||
199
doc/html/rouge-github.css
Normal file
199
doc/html/rouge-github.css
Normal file
@@ -0,0 +1,199 @@
|
||||
.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;
|
||||
}
|
||||
BIN
doc/html/skin.png
Normal file
BIN
doc/html/skin.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.1 KiB |
478
doc/html/zajo-dark.css
Normal file
478
doc/html/zajo-dark.css
Normal file
@@ -0,0 +1,478 @@
|
||||
/* 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}
|
||||
468
doc/html/zajo-light.css
Normal file
468
doc/html/zajo-light.css
Normal file
@@ -0,0 +1,468 @@
|
||||
/* 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}
|
||||
61
doc/introduction.adoc
Normal file
61
doc/introduction.adoc
Normal file
@@ -0,0 +1,61 @@
|
||||
|
||||
# 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?
|
||||
|
||||
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,
|
||||
https://openaccess.wgtn.ac.nz/articles/thesis/Multiple_Dispatch_in_Practice/16959112/1[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{plus}{plus}, 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
|
||||
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2216.pdf[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.
|
||||
62
doc/map_vptr.adoc
Normal file
62
doc/map_vptr.adoc
Normal file
@@ -0,0 +1,62 @@
|
||||
|
||||
## vptr_map
|
||||
|
||||
### Synopsis
|
||||
|
||||
```c++
|
||||
namespace boost::openmethod::policies {
|
||||
|
||||
### Synopsis
|
||||
|
||||
template<
|
||||
class Policy, bool IndirectVptr,
|
||||
class Map = std::unordered_map<
|
||||
type_id,
|
||||
std::conditional_t<IndirectVptr, const vptr_type*, vptr_type>>>
|
||||
class vptr_map : extern_vptr {
|
||||
static Map vptrs;
|
||||
|
||||
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.
|
||||
|
||||
`Policy` is the policy containing the facet.
|
||||
|
||||
`Map` is an `AssociativeContainer`. The `mapped_type` is a pointer to a
|
||||
`vptr_type` if `UseIndirectVptrs` is `void`, or a pointer to a `vptr_type` if
|
||||
`UseIndirectVptrs` is `indirect_vptr`.
|
||||
|
||||
### Members
|
||||
|
||||
#### register_vptrs
|
||||
|
||||
```c++
|
||||
template<typename ForwardIterator>
|
||||
auto register_vptrs(ForwardIterator first, ForwardIterator last) -> void;
|
||||
```
|
||||
|
||||
Stores the pointers to v-tables in a _Map_.
|
||||
|
||||
#### dynamic_vptr
|
||||
|
||||
```c++
|
||||
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` facet, checks if _Class_ is
|
||||
registered. If it is not, and _Policy_ contains a `error_handler` facet, calls
|
||||
its `error` function; then calls `abort`.
|
||||
152
doc/method.adoc
Normal file
152
doc/method.adoc
Normal file
@@ -0,0 +1,152 @@
|
||||
|
||||
|
||||
## method
|
||||
|
||||
### Synopsis
|
||||
|
||||
```c++
|
||||
namespace boost::openmethod {
|
||||
|
||||
template<
|
||||
typename Method, typename ReturnType,
|
||||
class Policy = BOOST_OPENMETHOD_DEFAULT_POLICY>
|
||||
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,{nbsp}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
|
||||
|
||||
```c++
|
||||
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
|
||||
|
||||
```c++
|
||||
~method();
|
||||
```
|
||||
|
||||
Remove the method from the list of methods registered in `Policy`.
|
||||
|
||||
#### operator()
|
||||
|
||||
```c++
|
||||
auto operator()(CallParameters... args) const -> ReturnType;
|
||||
```
|
||||
|
||||
Call the method with the arguments `args`.
|
||||
|
||||
`CallParameters` are the `Parameters` without the `virtual_` decorators. Note
|
||||
that `virtual_ptr`{empty}s 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. If the set is empty, call the error handler (if present in the policy), then
|
||||
terminate the program with `abort`
|
||||
|
||||
3. 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.
|
||||
|
||||
4. If the resulting set contains only one overrider, call it.
|
||||
|
||||
5. If the return type is a registered polymorphic type, remove all the
|
||||
overriders that return a less specific type than the others.
|
||||
|
||||
6. If the resulting set contains only one overrider, call it.
|
||||
|
||||
7. 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.
|
||||
|
||||
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. If a function named `boost_openmethod_vptr` that takes `result` and returns a
|
||||
`vptr_type` exists, call it.
|
||||
|
||||
3. Call `Policy::dynamic_vptr(result)`.
|
||||
|
||||
#### fn
|
||||
|
||||
```c++
|
||||
static method fn;
|
||||
```
|
||||
|
||||
The `method`{empty}'s unique instance. The method is called via the call
|
||||
operator on `fn`: `method::fn(args...)`.
|
||||
|
||||
#### override
|
||||
|
||||
```c++
|
||||
template<auto... Functions>
|
||||
struct override;
|
||||
```
|
||||
|
||||
Add _Functions_ to the overriders of `method`.
|
||||
|
||||
#### next
|
||||
|
||||
```c++
|
||||
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.
|
||||
64
doc/method_override.adoc
Normal file
64
doc/method_override.adoc
Normal file
@@ -0,0 +1,64 @@
|
||||
|
||||
[#method_override]
|
||||
## method::override
|
||||
|
||||
### Synopsis
|
||||
|
||||
```c++
|
||||
namespace boost::openmethod {
|
||||
|
||||
template<typename Signature, typename ReturnType, class Policy>
|
||||
template<auto... Functions>
|
||||
struct method<Signature, ReturnType, Policy>::override {
|
||||
override();
|
||||
~override();
|
||||
};
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Usage:
|
||||
```c++
|
||||
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_ptr`{empty}s 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
|
||||
|
||||
```c++
|
||||
override<Functions>::override();
|
||||
```
|
||||
|
||||
Add _Functions_ to the overriders of `method`.
|
||||
|
||||
#### Destructor
|
||||
|
||||
```c++
|
||||
override<Functions>::~method();
|
||||
```
|
||||
|
||||
Remove _Functions_ from the overriders of `method`.
|
||||
35
doc/minimal_rtti.adoc
Normal file
35
doc/minimal_rtti.adoc
Normal file
@@ -0,0 +1,35 @@
|
||||
|
||||
## minimal_rtti
|
||||
|
||||
### Synopsis
|
||||
|
||||
```c++
|
||||
struct minimal_rtti : virtual rtti {
|
||||
template<typename Class>
|
||||
static auto static_type() -> type_id;
|
||||
};
|
||||
```
|
||||
|
||||
### Description
|
||||
|
||||
`minimal_rtti` is an implementation of the `rtti` facet that only uses static
|
||||
type information.
|
||||
|
||||
`minimal_rtti` provides the only function strictly required for the `rtti`
|
||||
facet.
|
||||
|
||||
This facet can be used in programs that call methods solely via
|
||||
`virtual_ptr`{empty}s created with the "final" constructs. Virtual inheritance
|
||||
is not supported. Classes are not required to be polymorphic.
|
||||
|
||||
### Members
|
||||
|
||||
|
||||
#### static_type
|
||||
|
||||
```c++
|
||||
template<class Class>
|
||||
static auto static_type() -> type_id;
|
||||
```
|
||||
|
||||
Returns the address of a local static `char` variable, cast to `type_id`.
|
||||
20
doc/multiple_dispatch.adoc
Normal file
20
doc/multiple_dispatch.adoc
Normal file
@@ -0,0 +1,20 @@
|
||||
|
||||
## Multiple Dispatch
|
||||
|
||||
A method can have more than one `virtual_ptr` parameter. For example:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
include::{examplesdir}/hello_world.cpp[tag=multi]
|
||||
----
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
include::{examplesdir}/hello_world.cpp[tag=multi_call,indent=0]
|
||||
----
|
||||
|
||||
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.
|
||||
7
doc/multiple_inheritance.adoc
Normal file
7
doc/multiple_inheritance.adoc
Normal file
@@ -0,0 +1,7 @@
|
||||
|
||||
## Multiple Inheritance
|
||||
|
||||
Multiple inheritance is supported, with the exception of repeated inheritance.
|
||||
|
||||
Virtual inheritance is supported, but it incurs calls to `dynamic_cast` to cast
|
||||
the method's arguments to the types required by the overrider.
|
||||
28
doc/openmethod-theme.yml
Normal file
28
doc/openmethod-theme.yml
Normal file
@@ -0,0 +1,28 @@
|
||||
extends: default
|
||||
base:
|
||||
font:
|
||||
color: #404040
|
||||
literal:
|
||||
font:
|
||||
family: Courier
|
||||
color: #000000
|
||||
admonition:
|
||||
icon:
|
||||
note:
|
||||
stroke-color: #000000
|
||||
tip:
|
||||
stroke-color: #000000
|
||||
warning:
|
||||
stroke-color: #FF5100
|
||||
important:
|
||||
stroke-color: #FF5100
|
||||
caution:
|
||||
stroke-color: #FF5100
|
||||
conum:
|
||||
font:
|
||||
glyphs: circled
|
||||
color: #000000
|
||||
link:
|
||||
text-decoration: underline
|
||||
text-decoration-width: 0.5
|
||||
font-color: #000000
|
||||
19
doc/openmethod.adoc
Normal file
19
doc/openmethod.adoc
Normal file
@@ -0,0 +1,19 @@
|
||||
|
||||
# Boost.OpenMethod
|
||||
Jean-Louis Leroy
|
||||
:toc: left
|
||||
:toclevels: 3
|
||||
:idprefix:
|
||||
:listing-caption: Code Example
|
||||
:table-caption: Illustration
|
||||
:docinfo: private-footer
|
||||
:source-highlighter: rouge
|
||||
:source-language: c++
|
||||
|
||||
:leveloffset: +1
|
||||
|
||||
include::introduction.adoc[]
|
||||
include::tutorial.adoc[]
|
||||
include::reference.adoc[]
|
||||
|
||||
:leveloffset: -1
|
||||
102
doc/performance.adoc
Normal file
102
doc/performance.adoc
Normal file
@@ -0,0 +1,102 @@
|
||||
|
||||
## Performance
|
||||
|
||||
Open-methods are almost as fast as ordinary virtual member functions when
|
||||
compiled with optimization.
|
||||
|
||||
clang compiles the following code:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
include::{examplesdir}/hello_world.cpp[tag=call_poke_via_ref]
|
||||
----
|
||||
|
||||
...to this on the x64 architecture (variable names have been shortened for
|
||||
readability):
|
||||
|
||||
[source,asm]
|
||||
----
|
||||
mov rax, qword ptr [rsi]
|
||||
mov rdx, qword ptr [rip + hash_mult]
|
||||
imul rdx, qword ptr [rax - 8]
|
||||
movzx ecx, byte ptr [rip + hash_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:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
include::{examplesdir}/ast.cpp[tag=ast]
|
||||
----
|
||||
|
||||
The `Negate` overrider compiles to:
|
||||
|
||||
[source,asm]
|
||||
----
|
||||
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:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
include::{examplesdir}/ast.cpp[tag=final,indent=0]
|
||||
----
|
||||
|
||||
...compiles to:
|
||||
|
||||
```asm
|
||||
;; 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.
|
||||
91
doc/policies.adoc
Normal file
91
doc/policies.adoc
Normal file
@@ -0,0 +1,91 @@
|
||||
|
||||
## 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 _facets_. 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 facets in
|
||||
the same policy as part of their implementation. See the reference for a list of
|
||||
facets and stock implementations. Policies and facets are placed in the
|
||||
`boost::openmethod::policies` namespace. Two policies are provided by the
|
||||
library: `release` and `debug`.
|
||||
|
||||
`release` contains the following facets:
|
||||
|
||||
[cols="1,1,1"]
|
||||
|===
|
||||
|facet |implementation |role
|
||||
|
||||
| rtti
|
||||
| std_rtti
|
||||
| provides type information for classes and objects
|
||||
|
||||
| vptr
|
||||
| vptr_vector
|
||||
| stores vptrs in a global vector
|
||||
|
||||
| type_hash
|
||||
| fast_perfect_hash
|
||||
| hash type id to an index in a vector
|
||||
|
||||
| error_handler
|
||||
| vectored_error_handler
|
||||
| calls a handler via a `std::function`
|
||||
|
||||
|===
|
||||
|
||||
`policies::debug` contains the same facets as `release`, plus a few more:
|
||||
|
||||
[cols="1,1,1"]
|
||||
|===
|
||||
|facet |implementation |role
|
||||
|
||||
| runtime_checks
|
||||
| (itself)
|
||||
| enables runtime checks
|
||||
|
||||
| error_output
|
||||
| basic_error_output
|
||||
| prints error descriptions to `stderr`
|
||||
|
||||
| trace_output
|
||||
| basic_trace_output
|
||||
| enables `initialize` to print information about dispatch table construction to `stderr`
|
||||
|
||||
|===
|
||||
|
||||
Policies, and some facets, 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 by
|
||||
adding or removing facets from existing policies. For example, `policies::debug`
|
||||
is a tweak of `policies::release`:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
namespace boost::openmethod::policies {
|
||||
|
||||
struct debug : release::add<
|
||||
runtime_checks, basic_error_output<debug>,
|
||||
basic_trace_output<debug>> {};
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
|
||||
`boost::openmethod::default_policy` 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_POLICY` _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_POLICY`
|
||||
has no effect. See below for examples.
|
||||
45
doc/reference.adoc
Normal file
45
doc/reference.adoc
Normal file
@@ -0,0 +1,45 @@
|
||||
|
||||
# Reference
|
||||
:toc:
|
||||
:toc-title:
|
||||
:idprefix: ref_
|
||||
|
||||
// include::headers.adoc[]
|
||||
|
||||
include::BOOST_OPENMETHOD.adoc[]
|
||||
include::BOOST_OPENMETHOD_OVERRIDE.adoc[]
|
||||
include::BOOST_OPENMETHOD_INLINE_OVERRIDE.adoc[]
|
||||
include::BOOST_OPENMETHOD_REGISTER.adoc[]
|
||||
include::BOOST_OPENMETHOD_CLASSES.adoc[]
|
||||
include::BOOST_OPENMETHOD_DEFAULT_POLICY.adoc[]
|
||||
include::BOOST_OPENMETHOD_NAME.adoc[]
|
||||
include::BOOST_OPENMETHOD_OVERRIDERS.adoc[]
|
||||
|
||||
include::typedefs.adoc[]
|
||||
include::method.adoc[]
|
||||
include::method_override.adoc[]
|
||||
include::virtual_ptr.adoc[]
|
||||
include::virtual_traits.adoc[]
|
||||
include::use_classes.adoc[]
|
||||
include::virtual_.adoc[]
|
||||
include::with_vptr.adoc[]
|
||||
|
||||
include::abstract_policy.adoc[]
|
||||
include::domain.adoc[]
|
||||
include::basic_policy.adoc[]
|
||||
include::rtti.adoc[]
|
||||
include::std_rtti.adoc[]
|
||||
include::deferred_static_rtti.adoc[]
|
||||
include::minimal_rtti.adoc[]
|
||||
include::vptr.adoc[]
|
||||
include::vector_vptr.adoc[]
|
||||
include::map_vptr.adoc[]
|
||||
include::type_hash.adoc[]
|
||||
include::error_handler.adoc[]
|
||||
include::vectored_error_handler.adoc[]
|
||||
include::throw_error_handler.adoc[]
|
||||
include::error_output.adoc[]
|
||||
include::basic_error_output.adoc[]
|
||||
include::trace_output.adoc[]
|
||||
include::basic_trace_output.adoc[]
|
||||
include::restricted_output_stream.adoc[]
|
||||
35
doc/restricted_output_stream.adoc
Normal file
35
doc/restricted_output_stream.adoc
Normal file
@@ -0,0 +1,35 @@
|
||||
|
||||
## RestrictedOutputStream
|
||||
|
||||
### Description
|
||||
|
||||
RestrictedOutputStream 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 `RestrictedOutputStream` provide the following functions:
|
||||
|
||||
[cols="a,a", options="header"]
|
||||
|
||||
|===
|
||||
|
||||
| Name
|
||||
| Description
|
||||
|
||||
| RestrictedOutputStream& operator<<(RestrictedOutputStream& os, const char* str)
|
||||
| Write a null-terminated string `str` to `os`
|
||||
|
||||
| RestrictedOutputStream& operator<<(RestrictedOutputStream& os, const std::string_view& view)
|
||||
| Write a view to `os
|
||||
|
||||
| RestrictedOutputStream& operator<<(RestrictedOutputStream& os, const void* value)
|
||||
| Write a representation of a pointer to `os`
|
||||
|
||||
| RestrictedOutputStream& operator<<(RestrictedOutputStream& os, std::size_t value)
|
||||
| Write an unsigned integer to `os`
|
||||
|
||||
|===
|
||||
199
doc/rouge-github.css
Normal file
199
doc/rouge-github.css
Normal file
@@ -0,0 +1,199 @@
|
||||
.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;
|
||||
}
|
||||
71
doc/rtti.adoc
Normal file
71
doc/rtti.adoc
Normal file
@@ -0,0 +1,71 @@
|
||||
|
||||
## rtti
|
||||
|
||||
### Synopsis
|
||||
|
||||
Defined in <boost/openmethod/policies/basic_policy.hpp>.
|
||||
|
||||
```c++
|
||||
namespace boost::openmethod::policies {
|
||||
|
||||
struct rtti {};
|
||||
|
||||
} // boost::openmethod::policies
|
||||
```
|
||||
|
||||
### Description
|
||||
|
||||
The `rtti` facet 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
|
||||
|
||||
#### static_type
|
||||
|
||||
```c++
|
||||
template<class Class>
|
||||
static auto static_type() -> type_id;
|
||||
```
|
||||
|
||||
Returns a `type_id` for `Class`.
|
||||
|
||||
#### dynamic_type
|
||||
|
||||
```c++
|
||||
template<class Class>
|
||||
static auto dynamic_type(const Class& obj) -> type_id;
|
||||
```
|
||||
|
||||
Returns a `type_id` for an object's dynamic type.
|
||||
|
||||
#### type_name
|
||||
|
||||
```c++
|
||||
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
|
||||
|
||||
```c++
|
||||
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
|
||||
|
||||
```c++
|
||||
template<typename D, typename B>
|
||||
static auto dynamic_cast_ref(B&& obj) -> D;
|
||||
```
|
||||
|
||||
Casts `obj` to `D`. Required only if using virtual inheritance.
|
||||
BIN
doc/skin.png
Normal file
BIN
doc/skin.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.1 KiB |
21
doc/smart_pointers.adoc
Normal file
21
doc/smart_pointers.adoc
Normal file
@@ -0,0 +1,21 @@
|
||||
|
||||
## 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:
|
||||
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
include::{examplesdir}/ast_unique_ptr.cpp[tag=ast,indent=0]
|
||||
----
|
||||
82
doc/std_rtti.adoc
Normal file
82
doc/std_rtti.adoc
Normal file
@@ -0,0 +1,82 @@
|
||||
|
||||
## std_rtti
|
||||
|
||||
### Synopsis
|
||||
|
||||
Defined in <boost/openmethod/policies/std_rtti.hpp>.
|
||||
|
||||
```c++
|
||||
namespace boost::openmethod::policies {
|
||||
|
||||
struct std_rtti : virtual 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` facet that uses standard RTTI.
|
||||
|
||||
### Members
|
||||
|
||||
#### static_type
|
||||
|
||||
```c++
|
||||
template<class Class>
|
||||
static type_id static_type();
|
||||
```
|
||||
|
||||
Return the address of `Class`'s `type_info`, cast to a `type_id`.
|
||||
|
||||
#### dynamic_type
|
||||
|
||||
```c++
|
||||
template<class Class>
|
||||
static type_id dynamic_type(const Class& obj);
|
||||
```
|
||||
|
||||
Return the address of `obj`{empty}'s `type_info`, cast to a `type_id`.
|
||||
|
||||
#### type_name
|
||||
|
||||
```c++
|
||||
template<typename Stream>
|
||||
static void type_name(type_id type, Stream& stream);
|
||||
```
|
||||
|
||||
Write the demangled name of the class identified by `type` to `stream`.
|
||||
Execute `stream << reinterpret_cast<const std::type_info*>(type)->name()`.
|
||||
|
||||
#### type_index
|
||||
|
||||
```c++
|
||||
static /*unspecified*/ type_index(type_id type);
|
||||
```
|
||||
|
||||
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
|
||||
|
||||
```c++
|
||||
template<typename Derived, typename Base>
|
||||
static Derived dynamic_cast_ref(Base&& obj);
|
||||
```
|
||||
|
||||
Cast `obj` using the `dynamic_cast` operator.
|
||||
33
doc/throw_error_handler.adoc
Normal file
33
doc/throw_error_handler.adoc
Normal file
@@ -0,0 +1,33 @@
|
||||
|
||||
## throw_error_handler
|
||||
|
||||
### Synopsis
|
||||
|
||||
Defined in <boost/openmethod/policies/throw_error_handler.hpp>.
|
||||
|
||||
```c++
|
||||
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` facet that
|
||||
throws the error as an exception.
|
||||
|
||||
### Members
|
||||
|
||||
#### error
|
||||
|
||||
```c++
|
||||
template<class Error>
|
||||
[[noreturn]] static auto error(const Error& error) -> void;
|
||||
```
|
||||
|
||||
Throws `error`.
|
||||
45
doc/trace_output.adoc
Normal file
45
doc/trace_output.adoc
Normal file
@@ -0,0 +1,45 @@
|
||||
|
||||
## trace_output
|
||||
|
||||
### Synopsis
|
||||
|
||||
Defined in <boost/openmethod/policies/basic_policy.hpp>.
|
||||
|
||||
```c++
|
||||
namespace boost::openmethod::policies {
|
||||
|
||||
struct trace_output {};
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Description
|
||||
|
||||
`trace_output` is a facet used to write trace messages.
|
||||
|
||||
`initialize` can be directed to describe the classes and methods in a policy,
|
||||
and how the dispatch tables are built, by including this facet in the policy,
|
||||
and setting `trace_enabled` to `true`. The content and the format of the
|
||||
description is not documented, beyond the guarantee that it provides an
|
||||
exhaustive account of table construction, and may change between major, minor
|
||||
and patch versions.
|
||||
|
||||
### Requirements
|
||||
|
||||
#### trace_enabled
|
||||
|
||||
```c++
|
||||
static bool trace_enabled;
|
||||
```
|
||||
|
||||
`true` if tracing is enabled, `false` otherwise.
|
||||
|
||||
#### trace_stream
|
||||
|
||||
```c++
|
||||
static RestrictedOutputStream trace_stream;
|
||||
```
|
||||
|
||||
A static variable that satisfies the requirements of `RestrictedOutputStream`.
|
||||
18
doc/tutorial.adoc
Normal file
18
doc/tutorial.adoc
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
[#tutorials]
|
||||
# Tutorials
|
||||
:toc:
|
||||
:toc-title:
|
||||
:idprefix: tutorials_
|
||||
:examplesdir: ../examples
|
||||
|
||||
include::hello_world.adoc[]
|
||||
include::multiple_dispatch.adoc[]
|
||||
include::friendship.adoc[]
|
||||
include::performance.adoc[]
|
||||
include::smart_pointers.adoc[]
|
||||
include::virtual_ptr_alt.adoc[]
|
||||
include::core_api.adoc[]
|
||||
include::policies.adoc[]
|
||||
include::error_handling.adoc[]
|
||||
include::custom_rtti.adoc[]
|
||||
98
doc/type_hash.adoc
Normal file
98
doc/type_hash.adoc
Normal file
@@ -0,0 +1,98 @@
|
||||
|
||||
## type_hash
|
||||
|
||||
### Synopsis
|
||||
|
||||
Defined in <boost/openmethod/policies/basic_policy.hpp>.
|
||||
|
||||
```c++
|
||||
namespace boost::openmethod::policies {
|
||||
|
||||
struct type_hash {};
|
||||
|
||||
} // boost::openmethod::policies
|
||||
```
|
||||
|
||||
### Description
|
||||
|
||||
`type_hash` is a facet that provides a hash function for a fixed set of
|
||||
`type_id`{empty}s.
|
||||
|
||||
### Requirements
|
||||
|
||||
### hash_type_id
|
||||
|
||||
```c++
|
||||
static auto hash_type_id(type_id type) -> type_id;
|
||||
```
|
||||
|
||||
Returns the hash of `type`.
|
||||
|
||||
#### hash_initialize
|
||||
|
||||
```c++
|
||||
template<typename ForwardIterator>
|
||||
static auto hash_initialize(ForwardIterator first, ForwardIterator last) -> Report;
|
||||
```
|
||||
|
||||
Finds a hash function for the `type_id`{empty}s 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>.
|
||||
|
||||
```c++
|
||||
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_id`{empty}s.
|
||||
|
||||
### Members
|
||||
|
||||
Find two factors
|
||||
|
||||
#### hash_type_id
|
||||
|
||||
```c++
|
||||
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` facet, `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 facet, if present, then calls `abort`.
|
||||
|
||||
#### hash_initialize
|
||||
|
||||
```c++
|
||||
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 facet, if present, the
|
||||
calls `abort`.
|
||||
|
||||
If the policy has a `trace_output` facet, `hash_initialize` uses it to write a
|
||||
summary of the search.
|
||||
37
doc/typedefs.adoc
Normal file
37
doc/typedefs.adoc
Normal file
@@ -0,0 +1,37 @@
|
||||
|
||||
## type_id
|
||||
|
||||
### Synopsis
|
||||
|
||||
Defined in `<boost/openmethod/policies/basic_policy.hpp>`.
|
||||
|
||||
```c++
|
||||
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>`.
|
||||
|
||||
```c++
|
||||
namespace boost::openmethod {
|
||||
|
||||
using vptr_type = const /*unspecified*/ *;
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
### Description
|
||||
|
||||
`vptr_type` is the type of a pointer to a v-table.
|
||||
58
doc/use_classes.adoc
Normal file
58
doc/use_classes.adoc
Normal file
@@ -0,0 +1,58 @@
|
||||
|
||||
## use_classes
|
||||
|
||||
### Synopsis
|
||||
|
||||
Defined in <boost/openmethod/core.hpp>.
|
||||
|
||||
```c++
|
||||
namespace boost::openmethod {
|
||||
|
||||
template<class... Classes, class Policy = BOOST_OPENMETHOD_DEFAULT_POLICY>
|
||||
struct use_classes {
|
||||
use_classes();
|
||||
~use_classes();
|
||||
};
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Usage:
|
||||
|
||||
```c++
|
||||
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_POLICY` when `<boost/openmethod/core.hpp>` is
|
||||
included. Subsequently changing it has no retroactive effect.
|
||||
|
||||
### Members
|
||||
|
||||
#### constructor
|
||||
|
||||
```c++
|
||||
use_classes();
|
||||
```
|
||||
|
||||
Registers `Classes` and their inheritance relationships in `Policy`.
|
||||
|
||||
#### destructor
|
||||
|
||||
```c++
|
||||
~use_classes();
|
||||
```
|
||||
|
||||
Removes `Classes` and their inheritance relationships from `Policy`.
|
||||
58
doc/vector_vptr.adoc
Normal file
58
doc/vector_vptr.adoc
Normal file
@@ -0,0 +1,58 @@
|
||||
|
||||
## vptr_vector
|
||||
|
||||
### Synopsis
|
||||
|
||||
Defined in <boost/openmethod/policies/vptr_vector.hpp>.
|
||||
|
||||
```c++
|
||||
namespace boost::openmethod::policies {
|
||||
|
||||
template<class Policy, typename UseIndirectVptrs = void>
|
||||
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 `UseIndirectVptrs` is `indirect_vptr`,
|
||||
stores pointers to pointers to the v-tables.
|
||||
|
||||
`Policy` is the policy containing the facet.
|
||||
|
||||
### Members
|
||||
|
||||
#### register_vptrs
|
||||
|
||||
```c++
|
||||
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` facet, call its `hash_initialize`
|
||||
function, and uses it to convert the `type_id`{empty}s to an index.
|
||||
|
||||
#### dynamic_vptr
|
||||
|
||||
```c++
|
||||
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` facet, uses it to convert the result to an index;
|
||||
otherwise, uses the `type_id` as the index.
|
||||
52
doc/vectored_error_handler.adoc
Normal file
52
doc/vectored_error_handler.adoc
Normal file
@@ -0,0 +1,52 @@
|
||||
|
||||
## vectored_error_handler
|
||||
|
||||
### Synopsis
|
||||
|
||||
Defined in <boost/openmethod/policies/vectored_error_handler.hpp>.
|
||||
|
||||
```c++
|
||||
namespace boost::openmethod::policies {
|
||||
|
||||
template<class Policy>
|
||||
class vectored_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
|
||||
|
||||
`vectored_error_handler` is an implementation of `error_handler` that calls a
|
||||
`std::function` to handle the error.
|
||||
|
||||
### Members
|
||||
|
||||
#### error
|
||||
|
||||
```c++
|
||||
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 `error_output` facet, use it to print a description
|
||||
of `error`.
|
||||
|
||||
#### error
|
||||
|
||||
```c++
|
||||
static auto set_error_handler(function_type handler) -> function_type;
|
||||
```
|
||||
|
||||
Sets `handler` as the function to call in case of error.
|
||||
24
doc/virtual_.adoc
Normal file
24
doc/virtual_.adoc
Normal file
@@ -0,0 +1,24 @@
|
||||
|
||||
|
||||
## virtual_
|
||||
|
||||
### Synopsis
|
||||
|
||||
Defined in `<boost/openmethod/core.hpp>`.
|
||||
|
||||
```c++
|
||||
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&&`, `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.
|
||||
289
doc/virtual_ptr.adoc
Normal file
289
doc/virtual_ptr.adoc
Normal file
@@ -0,0 +1,289 @@
|
||||
|
||||
[#virtual_ptr]
|
||||
:idprefix: virtual_ptr_
|
||||
|
||||
## virtual_ptr
|
||||
|
||||
### Synopsis
|
||||
|
||||
`virtual_ptr` is defined in `<boost/openmethod/core.hpp>`.
|
||||
|
||||
```c++
|
||||
namespace boost::openmethod {
|
||||
|
||||
template<class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_POLICY>
|
||||
class virtual_ptr {
|
||||
public:
|
||||
static constexpr bool is_smart_ptr = /* see below */;
|
||||
using element_type = /* see below */;
|
||||
|
||||
template<class Other> virtual_ptr(Other& other);
|
||||
template<class Other> virtual_ptr(const Other& other);
|
||||
template<class Other> virtual_ptr(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_POLICY>;
|
||||
|
||||
template<class Class>
|
||||
inline auto final_virtual_ptr(Class& obj) -> virtual_ptr<
|
||||
Class, BOOST_OPENMETHOD_DEFAULT_POLICY>;
|
||||
|
||||
template<class Policy, class Class>
|
||||
inline auto final_virtual_ptr(Class& obj) -> virtual_ptr<Class, Policy>;
|
||||
|
||||
template<class Left, class Right, class Policy>
|
||||
bool operator==(
|
||||
const virtual_ptr<Left, Policy>& left,
|
||||
const virtual_ptr<Right, Policy>& right);
|
||||
|
||||
template<class Left, class Right, class Policy>
|
||||
bool operator!=(
|
||||
const virtual_ptr<Left, Policy>& left,
|
||||
const virtual_ptr<Right, Policy>& right);
|
||||
|
||||
} // namespace boost::openmethod
|
||||
```
|
||||
|
||||
Defined in `<boost/openmethod/shared_ptr.hpp>`:
|
||||
|
||||
```c++
|
||||
namespace boost::openmethod {
|
||||
|
||||
template<class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_POLICY>
|
||||
using shared_virtual_ptr = virtual_ptr<std::shared_ptr<Class>, Policy>;
|
||||
|
||||
template<
|
||||
class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_POLICY, typename... T>
|
||||
inline auto make_shared_virtual(T&&... args);
|
||||
|
||||
}
|
||||
```
|
||||
Defined in `<boost/openmethod/unique_ptr.hpp>`:
|
||||
|
||||
```c++
|
||||
namespace boost::openmethod {
|
||||
|
||||
template<class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_POLICY>
|
||||
using unique_virtual_ptr = virtual_ptr<std::unique_ptr<Class>, Policy>;
|
||||
|
||||
template<
|
||||
class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_POLICY, typename... T>
|
||||
inline auto make_unique_virtual(T&&... args);
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
### 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 allowed.
|
||||
|
||||
`virtual_ptr` does not have a default constructor, nor a "null" state. In that
|
||||
respect, it behaves more like a reference than a pointer. The only reason why it
|
||||
is not called `virtual_ref` is to save the name for the day C++ will support
|
||||
smart references.
|
||||
|
||||
### Members
|
||||
|
||||
#### is_smart_ptr
|
||||
|
||||
```c++
|
||||
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
|
||||
|
||||
```c++
|
||||
using element_type = std::conditional_t<
|
||||
is_smart_ptr, typename Class::element_type, Class>;
|
||||
```
|
||||
|
||||
The class of the object pointed to.
|
||||
|
||||
#### constructors
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
template<class Other> virtual_ptr(Other& other); // 1
|
||||
template<class Other> virtual_ptr(const Other& other); // 2
|
||||
template<class Other> virtual_ptr(Other&& other); // 3
|
||||
----
|
||||
|
||||
(1), (2) If `virtual_ptr` uses a plain pointer, `other` must be a lvalue
|
||||
reference to an object of a registered class, or to a `virtual_ptr` (plain or
|
||||
smart). If `virtual_ptr` uses a smart pointer, `other` must be a reference to a smart
|
||||
pointer, or a smart `virtual_ptr`.
|
||||
|
||||
(3) Smart `virtual_ptr` only. Constructs a `virtual_ptr` from a smart pointer or
|
||||
a smart `virtual_ptr`. The (smart) object pointer is moved from `other`.
|
||||
|
||||
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_ptr`{empty}s.
|
||||
|
||||
|
||||
#### final
|
||||
|
||||
```c++
|
||||
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
|
||||
|
||||
```c++
|
||||
auto get() const -> element_type*;
|
||||
```
|
||||
|
||||
Returns a pointer to the object.
|
||||
|
||||
#### operator->
|
||||
|
||||
```c++
|
||||
auto operator->() const -> element_type*;
|
||||
```
|
||||
|
||||
Returns a pointer to the object.
|
||||
|
||||
#### operator*
|
||||
|
||||
```c++
|
||||
auto operator*() const -> element_type&;
|
||||
```
|
||||
|
||||
Returns a reference to the object.
|
||||
|
||||
#### pointer
|
||||
|
||||
```c++
|
||||
auto pointer() const;
|
||||
```
|
||||
|
||||
Returns a reference to the object pointer, which can be either a plain pointer
|
||||
or a smart pointer.
|
||||
|
||||
#### cast
|
||||
|
||||
```c++
|
||||
template<typename Other>
|
||||
auto cast() const -> virtual_ptr<Other, Policy>;
|
||||
```
|
||||
|
||||
Returns a `virtual_ptr` to the same object, cast to `Other`.
|
||||
|
||||
### Deduction guide
|
||||
|
||||
```c++
|
||||
template<class Class>
|
||||
virtual_ptr(Class&) -> virtual_ptr<Class, BOOST_OPENMETHOD_DEFAULT_POLICY>;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Non-members
|
||||
|
||||
#### virtual_shared_ptr
|
||||
|
||||
```c++
|
||||
template<class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_POLICY>
|
||||
using virtual_shared_ptr = virtual_ptr<std::shared_ptr<Class>, Policy>;
|
||||
```
|
||||
|
||||
Convenience alias for `virtual_ptr<std::shared_ptr<Class>, Policy>`.
|
||||
|
||||
#### virtual_unique_ptr
|
||||
|
||||
```c++
|
||||
template<class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_POLICY>
|
||||
using virtual_unique_ptr = virtual_ptr<std::unique_ptr<Class>, Policy>;
|
||||
```
|
||||
|
||||
Convenience alias for `virtual_ptr<std::unique_ptr<Class>, Policy>`.
|
||||
|
||||
#### final_virtual_ptr
|
||||
|
||||
```c++
|
||||
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_POLICY` is used.
|
||||
|
||||
#### make_virtual_shared
|
||||
|
||||
```c++
|
||||
template<
|
||||
class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_POLICY, typename... T>
|
||||
inline auto make_virtual_shared(T&&... args);
|
||||
```
|
||||
|
||||
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_virtual_unique
|
||||
|
||||
```c++
|
||||
template<
|
||||
class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_POLICY, typename... T>
|
||||
inline auto make_virtual_unique(T&&... args);
|
||||
```
|
||||
|
||||
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==
|
||||
|
||||
```c++
|
||||
template<class Left, class Right, class Policy>
|
||||
bool operator==(
|
||||
const virtual_ptr<Left, Policy>& left,
|
||||
const virtual_ptr<Right, Policy>& right);
|
||||
```
|
||||
|
||||
Compares two `virtual_ptr` objects for equality.
|
||||
|
||||
#### operator!=
|
||||
|
||||
```c++
|
||||
template<class Left, class Right, class Policy>
|
||||
bool operator!=(
|
||||
const virtual_ptr<Left, Policy>& left,
|
||||
const virtual_ptr<Right, Policy>& right);
|
||||
```
|
||||
|
||||
Compares two `virtual_ptr` objects for inequality.
|
||||
76
doc/virtual_ptr_alt.adoc
Normal file
76
doc/virtual_ptr_alt.adoc
Normal file
@@ -0,0 +1,76 @@
|
||||
|
||||
## 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:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
include::{examplesdir}/virtual_.cpp[tag=virtual_parameter,indent=0]
|
||||
|
||||
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_policy`
|
||||
(more on policies below).
|
||||
|
||||
In the following example, we embed a vptr in the object, just like the vptr for
|
||||
native virtual functions:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
include::{examplesdir}/virtual_.cpp[tag=virtual_intrusive,indent=0]
|
||||
|
||||
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 `with_vptr` CRTP class automates the creation and management of embedded
|
||||
vptrs.
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
include::{examplesdir}/virtual_.cpp[tag=with_vptr,indent=0]
|
||||
|
||||
int main() {
|
||||
boost::openmethod::initialize();
|
||||
|
||||
Cat cat;
|
||||
poke(std::cout, cat); // hiss
|
||||
}
|
||||
----
|
||||
|
||||
If `with_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. `with_vptr` also takes care of registering the classes, so this time
|
||||
the call to `BOOST_OPENMETHOD_CLASSES` is not needed.
|
||||
92
doc/virtual_traits.adoc
Normal file
92
doc/virtual_traits.adoc
Normal file
@@ -0,0 +1,92 @@
|
||||
|
||||
## virtual_traits
|
||||
|
||||
### Synopsis
|
||||
|
||||
Defined in <boost/openmethod/core.hpp>.
|
||||
|
||||
```c++
|
||||
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&&`
|
||||
* `std::shared_ptr<T>`: defined in <boost/openmethod/shared_ptr.hpp>
|
||||
* `const std::shared_ptr<T>&`: defined in <boost/openmethod/shared_ptr.hpp>
|
||||
* `std::unique_ptr<T>`: defined in <boost/openmethod/unique_ptr.hpp>
|
||||
|
||||
### Members
|
||||
|
||||
#### virtual_type
|
||||
|
||||
```c++
|
||||
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
|
||||
|
||||
```c++
|
||||
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
|
||||
|
||||
```c++
|
||||
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
|
||||
|
||||
```c++
|
||||
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>`.
|
||||
110
doc/vptr.adoc
Normal file
110
doc/vptr.adoc
Normal file
@@ -0,0 +1,110 @@
|
||||
|
||||
## vptr
|
||||
|
||||
### Synopsis
|
||||
|
||||
Defined in <boost/openmethod/policies/basic_policy.hpp>.
|
||||
|
||||
```c++
|
||||
namespace boost::openmethod::policies {
|
||||
|
||||
struct vptr {};
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
### Description
|
||||
|
||||
`vptr` is a facet that obtains a pointer to the v-table for an object.
|
||||
|
||||
OpenMethod implements method dispatch in a way similar to native virtual
|
||||
function dispatch: for each virtual argument, fetch a pointer to the dispatch
|
||||
data (known as the v-table), and use it to select a pointer to a function.
|
||||
OpenMethod v-tables contain pointers to functions for unary methods, and, for
|
||||
multi-methods, pointers to, and coordinates in, a multi-dimensional table of
|
||||
pointers to functions.
|
||||
|
||||
The `vptr` facet is used during method call to fetch the vptr for virtual
|
||||
arguments corresponding to the `virtual_` parameters in the method
|
||||
declaration. It is also used by the constructor of `virtual_ptr` to obtain a
|
||||
vptr on the basis of an object's dynamic type.
|
||||
|
||||
`virtual_ptr::final`, and the related convenience functions, assume that the
|
||||
static and dynamic types of their argument are the same. The vptr is obtained
|
||||
statically from the policy's `static_vptr<Class>` member. It is conceivable
|
||||
to organize an entire program around the "final" constructs; thus, the `vptr`
|
||||
facet is optional.
|
||||
|
||||
### Requirements
|
||||
|
||||
#### dynamic_vptr;
|
||||
|
||||
```c++
|
||||
template<class Class>
|
||||
static auto dynamic_vptr(const Class& obj) -> const vptr_type&;
|
||||
```
|
||||
|
||||
Returns a pointer to the v-table for `obj`.
|
||||
|
||||
NOTE: `dynamic_vptr` _must_ return a reference to the pointer, not a value. This
|
||||
is required for indirect `virtual_ptr`{empty}s.
|
||||
|
||||
## extern_vptr
|
||||
|
||||
### Synopsis
|
||||
|
||||
```c++
|
||||
struct extern_vptr : virtual vptr {};
|
||||
```
|
||||
|
||||
### Description
|
||||
|
||||
`extern_vptr` is a specialization of `vptr` that stores vptrs outside of the
|
||||
objects.
|
||||
|
||||
### Requirements
|
||||
|
||||
The requirements of `vptr`, plus the following.
|
||||
|
||||
#### register_vptrs
|
||||
|
||||
```c++
|
||||
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:
|
||||
|
||||
```c++
|
||||
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 the class.
|
||||
|
||||
`vptr` returns a _reference_ to a _static_ variable containing a pointer to the
|
||||
v-table for a registered 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
|
||||
|
||||
```c++
|
||||
struct indirect_vptr {};
|
||||
```
|
||||
|
||||
### Description
|
||||
|
||||
`indirect_vptr` is a facet that makes `virtual_ptr`{empty}s and `with_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 facet is its own implementation.
|
||||
77
doc/with_vptr.adoc
Normal file
77
doc/with_vptr.adoc
Normal file
@@ -0,0 +1,77 @@
|
||||
|
||||
## with_vptr
|
||||
|
||||
### Synopsis
|
||||
|
||||
Defined in <boost/openmethod/core.hpp>.
|
||||
|
||||
```c++
|
||||
namespace boost::openmethod {
|
||||
|
||||
template<class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_POLICY>
|
||||
class with_vptr {
|
||||
protected:
|
||||
with_vptr();
|
||||
~with_vptr();
|
||||
friend auto boost_openmethod_vptr(const Class& obj) -> vptr_type;
|
||||
};
|
||||
|
||||
template<class Class, class Base, class... MoreBases>
|
||||
class with_vptr {
|
||||
protected:
|
||||
with_vptr();
|
||||
~with_vptr();
|
||||
friend auto boost_openmethod_vptr(const Class& obj) -> vptr_type;
|
||||
// if sizeof(MoreBases...) > 0
|
||||
};
|
||||
|
||||
} // namespace boost::openmethod
|
||||
```
|
||||
|
||||
### Description
|
||||
|
||||
`with_vptr` is a CRTP class template that embeds and manages a vptr across a
|
||||
class hierarchy.
|
||||
|
||||
If `Class` has no `Bases`, `with_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, `with_vptr` may also declare one or two free
|
||||
functions (`boost_openmethod_policy` and `boost_openmethod_bases`) at certain
|
||||
levels of the hierarchy.
|
||||
|
||||
### Members
|
||||
|
||||
#### constructor
|
||||
|
||||
```c++
|
||||
with_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
|
||||
|
||||
```c++
|
||||
~with_vptr();
|
||||
```
|
||||
|
||||
For each `Base`, sets the vptr to the v-table for that base.
|
||||
|
||||
#### Free Functions
|
||||
|
||||
```c++
|
||||
auto boost_openmethod_vptr(const Class& obj) -> vptr_type;
|
||||
```
|
||||
|
||||
Returns the vptr embedded in `obj`.
|
||||
478
doc/zajo-dark.css
Normal file
478
doc/zajo-dark.css
Normal file
@@ -0,0 +1,478 @@
|
||||
/* 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}
|
||||
468
doc/zajo-light.css
Normal file
468
doc/zajo-light.css
Normal file
@@ -0,0 +1,468 @@
|
||||
/* 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}
|
||||
106
examples/CMakeLists.txt
Normal file
106
examples/CMakeLists.txt
Normal file
@@ -0,0 +1,106 @@
|
||||
# Copyright (c) 2018-2024 Jean-Louis Leroy
|
||||
# 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)
|
||||
|
||||
if (CMAKE_BUILD_TYPE MATCHES "Release")
|
||||
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
add_compile_options(-save-temps -masm=intel)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_executable(virtual_func virtual_func.cpp)
|
||||
target_link_libraries(virtual_func Boost::openmethod)
|
||||
add_test(NAME virtual_func COMMAND virtual_func)
|
||||
|
||||
add_executable(ast ast.cpp)
|
||||
target_link_libraries(ast Boost::openmethod)
|
||||
add_test(NAME ast COMMAND ast)
|
||||
|
||||
add_executable(ast_unique_ptr ast_unique_ptr.cpp)
|
||||
target_link_libraries(ast_unique_ptr Boost::openmethod)
|
||||
add_test(NAME ast_unique_ptr COMMAND ast_unique_ptr)
|
||||
|
||||
add_executable(hello_world hello_world.cpp)
|
||||
target_link_libraries(hello_world Boost::openmethod)
|
||||
add_test(NAME hello_world COMMAND hello_world)
|
||||
|
||||
add_executable(friendship_all friendship.cpp)
|
||||
target_compile_definitions(friendship_all PRIVATE FRIEND_ALL)
|
||||
target_link_libraries(friendship_all Boost::openmethod)
|
||||
add_test(NAME friendship_add COMMAND friendship_all)
|
||||
|
||||
add_executable(friendship friendship.cpp)
|
||||
target_link_libraries(friendship Boost::openmethod)
|
||||
add_test(NAME friendship COMMAND friendship)
|
||||
|
||||
add_executable(friendship_across_namespaces_all friendship_across_namespaces.cpp)
|
||||
target_compile_definitions(friendship_across_namespaces_all PRIVATE FRIEND_ALL)
|
||||
target_link_libraries(friendship_across_namespaces_all Boost::openmethod)
|
||||
add_test(NAME friendship_across_namespaces_all COMMAND friendship_across_namespaces_all)
|
||||
|
||||
add_executable(friendship_across_namespaces friendship_across_namespaces.cpp)
|
||||
target_link_libraries(friendship_across_namespaces Boost::openmethod)
|
||||
add_test(NAME friendship_across_namespaces COMMAND friendship_across_namespaces)
|
||||
|
||||
add_executable(virtual_ptr virtual_ptr.cpp)
|
||||
target_link_libraries(virtual_ptr Boost::openmethod)
|
||||
add_test(NAME virtual_ptr COMMAND virtual_ptr)
|
||||
|
||||
add_executable(virtual_ virtual_.cpp)
|
||||
target_link_libraries(virtual_ Boost::openmethod)
|
||||
add_test(NAME virtual_ COMMAND virtual_)
|
||||
|
||||
add_executable(core_api core_api.cpp)
|
||||
target_link_libraries(core_api Boost::openmethod)
|
||||
add_test(NAME core_api COMMAND core_api)
|
||||
|
||||
add_executable(vectored_error_handler vectored_error_handler.cpp)
|
||||
target_link_libraries(vectored_error_handler Boost::openmethod)
|
||||
add_test(NAME vectored_error_handler COMMAND vectored_error_handler)
|
||||
|
||||
add_executable(throw_error_handler throw_error_handler.cpp)
|
||||
target_link_libraries(throw_error_handler Boost::openmethod)
|
||||
add_test(NAME throw_error_handler COMMAND throw_error_handler)
|
||||
|
||||
add_executable(custom_rtti custom_rtti.cpp)
|
||||
target_link_libraries(custom_rtti Boost::openmethod)
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
set_target_properties(custom_rtti PROPERTIES COMPILE_FLAGS "-fno-rtti")
|
||||
endif()
|
||||
add_test(NAME custom_rtti COMMAND custom_rtti)
|
||||
|
||||
add_executable(deferred_custom_rtti deferred_custom_rtti.cpp)
|
||||
target_link_libraries(deferred_custom_rtti Boost::openmethod)
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
set_target_properties(deferred_custom_rtti PROPERTIES COMPILE_FLAGS "-fno-rtti")
|
||||
endif()
|
||||
add_test(NAME deferred_custom_rtti COMMAND deferred_custom_rtti)
|
||||
|
||||
add_executable(slides slides.cpp)
|
||||
target_link_libraries(slides Boost::openmethod)
|
||||
add_test(NAME slides COMMAND slides)
|
||||
|
||||
add_executable(synopsis synopsis.cpp)
|
||||
target_link_libraries(synopsis Boost::openmethod)
|
||||
add_test(NAME synopsis COMMAND synopsis)
|
||||
|
||||
add_executable(matrix matrix.cpp)
|
||||
target_link_libraries(matrix Boost::openmethod)
|
||||
add_test(NAME matrix COMMAND matrix)
|
||||
|
||||
add_executable(accept_no_visitors accept_no_visitors.cpp)
|
||||
target_link_libraries(accept_no_visitors Boost::openmethod)
|
||||
add_test(NAME accept_no_visitors COMMAND accept_no_visitors)
|
||||
|
||||
add_executable(adventure adventure.cpp)
|
||||
target_link_libraries(adventure Boost::openmethod)
|
||||
add_test(NAME adventure COMMAND adventure)
|
||||
|
||||
add_executable(next next.cpp)
|
||||
target_link_libraries(next Boost::openmethod)
|
||||
add_test(NAME next COMMAND next)
|
||||
|
||||
add_executable(asteroids asteroids.cpp)
|
||||
target_link_libraries(asteroids Boost::openmethod)
|
||||
add_test(NAME asteroids COMMAND asteroids)
|
||||
123
examples/accept_no_visitors.cpp
Normal file
123
examples/accept_no_visitors.cpp
Normal file
@@ -0,0 +1,123 @@
|
||||
// Copyright (c) 2018-2025 Jean-Louis Leroy
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <boost/openmethod.hpp>
|
||||
#include <boost/openmethod/shared_ptr.hpp>
|
||||
#include <boost/openmethod/compiler.hpp>
|
||||
|
||||
using boost::openmethod::make_shared_virtual;
|
||||
using boost::openmethod::shared_virtual_ptr;
|
||||
|
||||
using std::cout;
|
||||
using std::string;
|
||||
|
||||
struct Node {
|
||||
virtual ~Node() {
|
||||
}
|
||||
};
|
||||
|
||||
struct Plus : Node {
|
||||
Plus(
|
||||
shared_virtual_ptr<const Node> left,
|
||||
shared_virtual_ptr<const Node> right)
|
||||
: left(left), right(right) {
|
||||
}
|
||||
|
||||
shared_virtual_ptr<const Node> left, right;
|
||||
};
|
||||
|
||||
struct Times : Node {
|
||||
Times(
|
||||
shared_virtual_ptr<const Node> left,
|
||||
shared_virtual_ptr<const Node> right)
|
||||
: left(left), right(right) {
|
||||
}
|
||||
|
||||
shared_virtual_ptr<const Node> left, right;
|
||||
};
|
||||
|
||||
struct Integer : Node {
|
||||
explicit Integer(int value) : value(value) {
|
||||
}
|
||||
int value;
|
||||
};
|
||||
|
||||
// =============================================================================
|
||||
// add behavior to existing classes, without changing them
|
||||
|
||||
BOOST_OPENMETHOD_CLASSES(Node, Plus, Times, Integer);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// evaluate
|
||||
|
||||
BOOST_OPENMETHOD(value, (virtual_ptr<const Node>), int);
|
||||
|
||||
BOOST_OPENMETHOD_OVERRIDE(value, (virtual_ptr<const Plus> expr), int) {
|
||||
return value(expr->left) + value(expr->right);
|
||||
}
|
||||
|
||||
BOOST_OPENMETHOD_OVERRIDE(value, (virtual_ptr<const Times> expr), int) {
|
||||
return value(expr->left) * value(expr->right);
|
||||
}
|
||||
|
||||
BOOST_OPENMETHOD_OVERRIDE(value, (virtual_ptr<const Integer> expr), int) {
|
||||
return expr->value;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// render as Forth
|
||||
|
||||
BOOST_OPENMETHOD(as_forth, (virtual_ptr<const Node>), string);
|
||||
|
||||
BOOST_OPENMETHOD_OVERRIDE(as_forth, (virtual_ptr<const Plus> expr), string) {
|
||||
return as_forth(expr->left) + " " + as_forth(expr->right) + " +";
|
||||
}
|
||||
|
||||
BOOST_OPENMETHOD_OVERRIDE(as_forth, (virtual_ptr<const Times> expr), string) {
|
||||
return as_forth(expr->left) + " " + as_forth(expr->right) + " *";
|
||||
}
|
||||
|
||||
BOOST_OPENMETHOD_OVERRIDE(as_forth, (virtual_ptr<const Integer> expr), string) {
|
||||
return std::to_string(expr->value);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// render as Lisp
|
||||
|
||||
BOOST_OPENMETHOD(as_lisp, (virtual_ptr<const Node>), string);
|
||||
|
||||
BOOST_OPENMETHOD_OVERRIDE(as_lisp, (virtual_ptr<const Plus> expr), string) {
|
||||
return "(plus " + as_lisp(expr->left) + " " + as_lisp(expr->right) + ")";
|
||||
}
|
||||
|
||||
BOOST_OPENMETHOD_OVERRIDE(as_lisp, (virtual_ptr<const Times> expr), string) {
|
||||
return "(times " + as_lisp(expr->left) + " " + as_lisp(expr->right) + ")";
|
||||
}
|
||||
|
||||
BOOST_OPENMETHOD_OVERRIDE(as_lisp, (virtual_ptr<const Integer> expr), string) {
|
||||
return std::to_string(expr->value);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
int main() {
|
||||
boost::openmethod::initialize();
|
||||
|
||||
shared_virtual_ptr<Node> expr = make_shared_virtual<Times>(
|
||||
make_shared_virtual<Integer>(2),
|
||||
make_shared_virtual<Plus>(
|
||||
make_shared_virtual<Integer>(3), make_shared_virtual<Integer>(4)));
|
||||
|
||||
cout << as_forth(expr) << " = " << as_lisp(expr) << " = " << value(expr)
|
||||
<< "\n";
|
||||
// error_output:
|
||||
// 2 3 4 + * = (times 2 (plus 3 4)) = 14
|
||||
|
||||
return 0;
|
||||
}
|
||||
128
examples/adventure.cpp
Normal file
128
examples/adventure.cpp
Normal file
@@ -0,0 +1,128 @@
|
||||
// Copyright (c) 2018-2025 Jean-Louis Leroy
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <boost/openmethod.hpp>
|
||||
#include <boost/openmethod/compiler.hpp>
|
||||
|
||||
struct Character {
|
||||
virtual ~Character() {
|
||||
}
|
||||
};
|
||||
|
||||
struct Warrior : Character {};
|
||||
|
||||
struct Device {
|
||||
virtual ~Device() {
|
||||
}
|
||||
};
|
||||
|
||||
struct Hands : Device {};
|
||||
struct Axe : Device {};
|
||||
struct Banana : Device {};
|
||||
|
||||
struct Creature {
|
||||
virtual ~Creature() {
|
||||
}
|
||||
};
|
||||
|
||||
struct Dragon : Creature {};
|
||||
struct Bear : Creature {};
|
||||
|
||||
BOOST_OPENMETHOD_CLASSES(
|
||||
Character, Warrior, Device, Hands, Axe, Banana, Creature, Dragon, Bear);
|
||||
|
||||
BOOST_OPENMETHOD(
|
||||
fight, (virtual_ptr<Character>, virtual_ptr<Creature>, virtual_ptr<Device>),
|
||||
std::string);
|
||||
|
||||
BOOST_OPENMETHOD_OVERRIDE(
|
||||
fight,
|
||||
(virtual_ptr<Character> x, virtual_ptr<Creature> y, virtual_ptr<Banana> z),
|
||||
std::string) {
|
||||
return "are you insane?";
|
||||
}
|
||||
|
||||
BOOST_OPENMETHOD_OVERRIDE(
|
||||
fight,
|
||||
(virtual_ptr<Character> x, virtual_ptr<Creature> y, virtual_ptr<Axe> z),
|
||||
std::string) {
|
||||
return "not agile enough to wield";
|
||||
}
|
||||
|
||||
BOOST_OPENMETHOD_OVERRIDE(
|
||||
fight,
|
||||
(virtual_ptr<Warrior> x, virtual_ptr<Creature> y, virtual_ptr<Axe> z),
|
||||
std::string) {
|
||||
return "and cuts it into pieces";
|
||||
}
|
||||
|
||||
BOOST_OPENMETHOD_OVERRIDE(
|
||||
fight, (virtual_ptr<Warrior> x, virtual_ptr<Dragon> y, virtual_ptr<Axe> z),
|
||||
std::string) {
|
||||
return "and dies a honorable death";
|
||||
}
|
||||
|
||||
BOOST_OPENMETHOD_OVERRIDE(
|
||||
fight,
|
||||
(virtual_ptr<Character> x, virtual_ptr<Dragon> y, virtual_ptr<Hands> z),
|
||||
std::string) {
|
||||
return "Congratulations! You have just vainquished a dragon with your bare "
|
||||
"hands"
|
||||
" (unbelievable, isn't it?)";
|
||||
}
|
||||
|
||||
int main() {
|
||||
boost::openmethod::initialize();
|
||||
|
||||
std::unique_ptr<Character> bob = std::make_unique<Character>(),
|
||||
rambo = std::make_unique<Warrior>();
|
||||
|
||||
std::unique_ptr<Creature> elliott = std::make_unique<Dragon>(),
|
||||
paddington = std::make_unique<Bear>();
|
||||
|
||||
std::unique_ptr<Device> hands = std::make_unique<Hands>(),
|
||||
axe = std::make_unique<Axe>(),
|
||||
chiquita = std::make_unique<Banana>();
|
||||
|
||||
std::cout << "bob fights elliot with axe:\n"
|
||||
<< fight(*bob, *elliott, *axe) << "\n";
|
||||
// bob fights elliot with axe:
|
||||
// not agile enough to wield
|
||||
|
||||
std::cout << "rambo fights paddington with axe:\n"
|
||||
<< fight(*rambo, *paddington, *axe) << "\n";
|
||||
// rambo fights paddington with axe:
|
||||
// and cuts it into pieces
|
||||
|
||||
std::cout << "rambo fights paddington with banana:\n"
|
||||
<< fight(*rambo, *paddington, *chiquita) << "\n";
|
||||
// rambo fights paddington with banana:
|
||||
// are you insane?
|
||||
|
||||
std::cout << "rambo fights elliott with axe:\n"
|
||||
<< fight(*rambo, *elliott, *axe) << "\n";
|
||||
// rambo fights elliott with axe:
|
||||
// and dies a honorable death
|
||||
|
||||
std::cout << "bob fights elliot with hands:\n"
|
||||
<< fight(*bob, *elliott, *hands) << "\n";
|
||||
// bob fights elliot with hands: Congratulations! You have just vainquished
|
||||
// a dragon with your bare hands (unbelievable, isn't it?)
|
||||
|
||||
std::cout << "rambo fights elliot with hands:\n"
|
||||
<< fight(*rambo, *elliott, *hands) << "\n";
|
||||
// rambo fights elliot with hands:
|
||||
// you just killed a dragon with your bare hands. Incredible isn't it?
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto call_fight(Character& character, Creature& creature, Device& device) {
|
||||
return fight(character, creature, device);
|
||||
}
|
||||
82
examples/ast.cpp
Normal file
82
examples/ast.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
// Copyright (c) 2018-2025 Jean-Louis Leroy
|
||||
// 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)
|
||||
|
||||
// clang-format off
|
||||
|
||||
// tag::ast[]
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/openmethod.hpp>
|
||||
#include <boost/openmethod/compiler.hpp>
|
||||
|
||||
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);
|
||||
|
||||
int main() {
|
||||
boost::openmethod::initialize();
|
||||
|
||||
Literal one(1), two(2);
|
||||
Plus sum(one, two);
|
||||
Negate neg(sum);
|
||||
|
||||
std::cout << value(neg) << "\n"; // -3
|
||||
|
||||
return 0;
|
||||
}
|
||||
// end::ast[]
|
||||
|
||||
int negate(virtual_ptr<Node> node) {
|
||||
return -value(node);
|
||||
}
|
||||
|
||||
#define main alt_main
|
||||
|
||||
int main() {
|
||||
// tag::final[]
|
||||
Literal one(1);
|
||||
Negate neg(boost::openmethod::final_virtual_ptr(one));
|
||||
// end::final[]
|
||||
|
||||
std::cout << value(boost::openmethod::final_virtual_ptr(neg)) << "\n"; // -3
|
||||
|
||||
return 0;
|
||||
}
|
||||
71
examples/ast_unique_ptr.cpp
Normal file
71
examples/ast_unique_ptr.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
// Copyright (c) 2018-2025 Jean-Louis Leroy
|
||||
// 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)
|
||||
|
||||
// clang-format off
|
||||
|
||||
// tag::ast[]
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
#include <boost/openmethod.hpp>
|
||||
#include <boost/openmethod/unique_ptr.hpp>
|
||||
#include <boost/openmethod/compiler.hpp>
|
||||
|
||||
using boost::openmethod::unique_virtual_ptr;
|
||||
using boost::openmethod::make_unique_virtual;
|
||||
|
||||
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);
|
||||
|
||||
int main() {
|
||||
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;
|
||||
}
|
||||
// end::ast[]
|
||||
68
examples/asteroids.cpp
Normal file
68
examples/asteroids.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
// asteroids.cpp
|
||||
// Copyright (c) 2018-2025 Jean-Louis Leroy
|
||||
// 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)
|
||||
|
||||
// Example for Wikipedia
|
||||
|
||||
#include <boost/openmethod.hpp>
|
||||
#include <boost/openmethod/compiler.hpp>
|
||||
|
||||
class Thing {
|
||||
public:
|
||||
virtual ~Thing() {
|
||||
}
|
||||
};
|
||||
|
||||
class Asteroid : public Thing {};
|
||||
|
||||
class Spaceship : public Thing {};
|
||||
|
||||
BOOST_OPENMETHOD_CLASSES(Thing, Spaceship, Asteroid);
|
||||
|
||||
BOOST_OPENMETHOD(collideWith, (virtual_ptr<Thing>, virtual_ptr<Thing>), void);
|
||||
|
||||
BOOST_OPENMETHOD_OVERRIDE(
|
||||
collideWith, (virtual_ptr<Thing> left, virtual_ptr<Thing> right), void) {
|
||||
// default collision handling
|
||||
}
|
||||
|
||||
BOOST_OPENMETHOD_OVERRIDE(
|
||||
collideWith, (virtual_ptr<Asteroid> left, virtual_ptr<Asteroid> right),
|
||||
void) {
|
||||
// handle Asteroid-Asteroid collision
|
||||
}
|
||||
|
||||
BOOST_OPENMETHOD_OVERRIDE(
|
||||
collideWith, (virtual_ptr<Asteroid> left, virtual_ptr<Spaceship> right),
|
||||
void) {
|
||||
// handle Asteroid-Spaceship collision
|
||||
}
|
||||
|
||||
BOOST_OPENMETHOD_OVERRIDE(
|
||||
collideWith, (virtual_ptr<Spaceship> left, virtual_ptr<Asteroid> right),
|
||||
void) {
|
||||
// handle Spaceship-Asteroid collision
|
||||
}
|
||||
|
||||
BOOST_OPENMETHOD_OVERRIDE(
|
||||
collideWith, (virtual_ptr<Spaceship> left, virtual_ptr<Spaceship> right),
|
||||
void) {
|
||||
// handle Spaceship-Spaceship collision
|
||||
}
|
||||
|
||||
int main() {
|
||||
boost::openmethod::initialize();
|
||||
|
||||
Asteroid a1, a2;
|
||||
Spaceship s1, s2;
|
||||
|
||||
collideWith(a1, a2);
|
||||
collideWith(a1, s1);
|
||||
|
||||
collideWith(s1, s2);
|
||||
collideWith(s1, a1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
103
examples/core_api.cpp
Normal file
103
examples/core_api.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
// Copyright (c) 2018-2025 Jean-Louis Leroy
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/openmethod/compiler.hpp>
|
||||
#include <boost/openmethod/core.hpp>
|
||||
|
||||
struct Animal {
|
||||
virtual ~Animal() = default;
|
||||
};
|
||||
|
||||
struct Cat : Animal {};
|
||||
|
||||
struct Dog : Animal {};
|
||||
|
||||
struct Bulldog : Dog {};
|
||||
|
||||
using namespace boost::openmethod;
|
||||
|
||||
// tag::method[]
|
||||
|
||||
#include <boost/openmethod/macros/name.hpp>
|
||||
|
||||
class BOOST_OPENMETHOD_NAME(poke);
|
||||
|
||||
using poke = method<
|
||||
BOOST_OPENMETHOD_NAME(poke)(std::ostream&, virtual_ptr<Animal>), void>;
|
||||
// end::method[]
|
||||
|
||||
// tag::poke_cat[]
|
||||
auto poke_cat(std::ostream& os, virtual_ptr<Cat> cat) {
|
||||
os << "hiss";
|
||||
}
|
||||
|
||||
static poke::override<poke_cat> override_poke_cat;
|
||||
// end::poke_cat[]
|
||||
|
||||
// tag::poke_dog[]
|
||||
#include <boost/openmethod/macros/register.hpp>
|
||||
|
||||
auto poke_dog(std::ostream& os, virtual_ptr<Dog> dog) {
|
||||
os << "bark";
|
||||
}
|
||||
|
||||
BOOST_OPENMETHOD_REGISTER(poke::override<poke_dog>);
|
||||
// end::poke_dog[]
|
||||
|
||||
// tag::poke_bulldog[]
|
||||
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>);
|
||||
// end::poke_bulldog[]
|
||||
|
||||
class BOOST_OPENMETHOD_NAME(pet);
|
||||
|
||||
auto pet_cat(std::ostream& os, virtual_ptr<Cat> cat) {
|
||||
os << "purr";
|
||||
}
|
||||
|
||||
auto pet_dog(std::ostream& os, virtual_ptr<Dog> dog) {
|
||||
os << "wag tail";
|
||||
}
|
||||
|
||||
using pet = method<
|
||||
BOOST_OPENMETHOD_NAME(pet)(std::ostream&, virtual_ptr<Animal>), void>;
|
||||
|
||||
BOOST_OPENMETHOD_REGISTER(pet::override<pet_cat, pet_dog>);
|
||||
|
||||
// tag::use_classes[]
|
||||
BOOST_OPENMETHOD_REGISTER(use_classes<Animal, Cat, Dog, Bulldog>);
|
||||
// end::use_classes[]
|
||||
|
||||
// tag::main[]
|
||||
int main() {
|
||||
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";
|
||||
// end::main[]
|
||||
|
||||
pet::fn(std::cout, *a); // prints "purr"
|
||||
std::cout << "\n";
|
||||
// tag::main[]
|
||||
|
||||
return 0;
|
||||
// end::main[]
|
||||
}
|
||||
99
examples/custom_rtti.cpp
Normal file
99
examples/custom_rtti.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
// Copyright (c) 2018-2025 Jean-Louis Leroy
|
||||
// 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)
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
struct Dog : Animal {
|
||||
Dog() : Animal(static_type) {
|
||||
}
|
||||
|
||||
static constexpr unsigned static_type = 3;
|
||||
};
|
||||
|
||||
#include <boost/openmethod/policies/basic_policy.hpp>
|
||||
#include <boost/openmethod/policies/vptr_vector.hpp>
|
||||
|
||||
// tag::facet[]
|
||||
namespace bom = boost::openmethod;
|
||||
|
||||
struct custom_rtti : bom::policies::rtti {
|
||||
template<typename T>
|
||||
static bom::type_id static_type() {
|
||||
if constexpr (std::is_base_of_v<Animal, T>) {
|
||||
return T::static_type;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static bom::type_id dynamic_type(const T& obj) {
|
||||
if constexpr (std::is_base_of_v<Animal, T>) {
|
||||
return obj.type;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
// end::facet[]
|
||||
|
||||
// tag::policy[]
|
||||
struct custom_policy : bom::policies::basic_policy<
|
||||
custom_policy, custom_rtti,
|
||||
bom::policies::vptr_vector<custom_policy>> {};
|
||||
|
||||
#define BOOST_OPENMETHOD_DEFAULT_POLICY custom_policy
|
||||
// end::policy[]
|
||||
|
||||
// tag::example[]
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/openmethod.hpp>
|
||||
#include <boost/openmethod/compiler.hpp>
|
||||
|
||||
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);
|
||||
|
||||
int main() {
|
||||
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;
|
||||
}
|
||||
// end::example[]
|
||||
155
examples/deferred_custom_rtti.cpp
Normal file
155
examples/deferred_custom_rtti.cpp
Normal file
@@ -0,0 +1,155 @@
|
||||
// Copyright (c) 2018-2025 Jean-Louis Leroy
|
||||
// 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)
|
||||
|
||||
// tag::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 void* cast_impl(unsigned target) {
|
||||
if (type_info.id == target) {
|
||||
return this;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
template<class Class>
|
||||
Class* cast() {
|
||||
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 void* cast_impl(unsigned target) {
|
||||
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;
|
||||
// end::classes[]
|
||||
|
||||
struct Dog : virtual Animal {
|
||||
Dog() {
|
||||
type = type_info.id;
|
||||
}
|
||||
|
||||
virtual void* cast_impl(unsigned target) {
|
||||
if (type_info.id == target) {
|
||||
return this;
|
||||
} else {
|
||||
return Animal::cast_impl(target);
|
||||
}
|
||||
}
|
||||
|
||||
static custom_type_info type_info;
|
||||
};
|
||||
|
||||
#include <boost/openmethod/policies/basic_policy.hpp>
|
||||
#include <boost/openmethod/policies/vptr_vector.hpp>
|
||||
|
||||
namespace bom = boost::openmethod;
|
||||
|
||||
struct custom_rtti : bom::policies::rtti {
|
||||
template<typename T>
|
||||
static bom::type_id static_type() {
|
||||
if constexpr (std::is_base_of_v<Animal, T>) {
|
||||
return T::type_info.id;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static bom::type_id dynamic_type(const T& obj) {
|
||||
if constexpr (std::is_base_of_v<Animal, T>) {
|
||||
return obj.type;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// tag::dynamic_cast_ref[]
|
||||
// to support virtual inheritance:
|
||||
template<typename Derived, typename Base>
|
||||
static Derived dynamic_cast_ref(Base&& obj) {
|
||||
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
|
||||
}
|
||||
}
|
||||
// end::dynamic_cast_ref[]
|
||||
};
|
||||
|
||||
struct custom_policy
|
||||
: bom::policies::basic_policy<
|
||||
custom_policy, custom_rtti, bom::policies::deferred_static_rtti,
|
||||
bom::policies::vptr_vector<custom_policy>> {};
|
||||
|
||||
#define BOOST_OPENMETHOD_DEFAULT_POLICY custom_policy
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/openmethod.hpp>
|
||||
#include <boost/openmethod/compiler.hpp>
|
||||
|
||||
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);
|
||||
|
||||
custom_type_info Dog::type_info;
|
||||
|
||||
int main() {
|
||||
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;
|
||||
}
|
||||
// end::example[]
|
||||
100
examples/friendship.cpp
Normal file
100
examples/friendship.cpp
Normal file
@@ -0,0 +1,100 @@
|
||||
// Copyright (c) 2018-2025 Jean-Louis Leroy
|
||||
// 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)
|
||||
|
||||
// clang-format off
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <boost/openmethod.hpp>
|
||||
|
||||
#ifdef FRIEND_ALL
|
||||
|
||||
// tag::friend_all[]
|
||||
class Cat;
|
||||
class Dog;
|
||||
|
||||
class Animal {
|
||||
// end::friend_all[]
|
||||
|
||||
public:
|
||||
Animal(std::string name) : name(name) {
|
||||
}
|
||||
virtual ~Animal() = default;
|
||||
// tag::friend_all[]
|
||||
// ...
|
||||
private:
|
||||
std::string name;
|
||||
|
||||
template<typename> friend struct BOOST_OPENMETHOD_OVERRIDERS(poke);
|
||||
};
|
||||
// end::friend_all[]
|
||||
|
||||
#else
|
||||
|
||||
// tag::friend[]
|
||||
class Cat;
|
||||
class Dog;
|
||||
|
||||
template<typename> struct BOOST_OPENMETHOD_OVERRIDERS(poke);
|
||||
|
||||
class Animal {
|
||||
// ...
|
||||
// end::friend[]
|
||||
public:
|
||||
Animal(std::string name) : name(name) {
|
||||
}
|
||||
virtual ~Animal() = default;
|
||||
|
||||
// tag::friend[]
|
||||
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>)>;
|
||||
};
|
||||
// end::friend[]
|
||||
|
||||
#endif
|
||||
|
||||
class Cat : public Animal {
|
||||
using Animal::Animal;
|
||||
};
|
||||
|
||||
class Dog : public Animal {
|
||||
using Animal::Animal;
|
||||
};
|
||||
|
||||
class Animal;
|
||||
|
||||
BOOST_OPENMETHOD(poke, (std::ostream&, virtual_ptr<Animal>), void);
|
||||
|
||||
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<Dog> dog), void) {
|
||||
os << dog->name << " barks";
|
||||
}
|
||||
|
||||
BOOST_OPENMETHOD_CLASSES(Animal, Cat, Dog);
|
||||
|
||||
#include <boost/openmethod/compiler.hpp>
|
||||
|
||||
int main() {
|
||||
boost::openmethod::initialize();
|
||||
|
||||
std::unique_ptr<Animal> a(new Cat("Felix"));
|
||||
std::unique_ptr<Animal> b(new Dog("Snoopy"));
|
||||
|
||||
poke(std::cout, *a); // Felix hisses
|
||||
std::cout << ".\n";
|
||||
|
||||
poke(std::cout, *b); // Snoopy barks
|
||||
std::cout << ".\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
114
examples/friendship_across_namespaces.cpp
Normal file
114
examples/friendship_across_namespaces.cpp
Normal file
@@ -0,0 +1,114 @@
|
||||
// Copyright (c) 2018-2025 Jean-Louis Leroy
|
||||
// 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)
|
||||
|
||||
// clang-format off
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <boost/openmethod.hpp>
|
||||
|
||||
#ifdef FRIEND_ALL
|
||||
|
||||
// tag::friend_all[]
|
||||
|
||||
namespace pets {
|
||||
template<typename> struct BOOST_OPENMETHOD_OVERRIDERS(poke);
|
||||
}
|
||||
|
||||
namespace core {
|
||||
class Animal {
|
||||
// end::friend_all[]
|
||||
|
||||
// tag::friend_all[]
|
||||
public:
|
||||
Animal(std::string name) : name(name) {
|
||||
}
|
||||
virtual ~Animal() = default;
|
||||
// ...
|
||||
private:
|
||||
std::string name;
|
||||
|
||||
template<typename> friend struct BOOST_OPENMETHOD_OVERRIDERS(pets::poke);
|
||||
};
|
||||
|
||||
BOOST_OPENMETHOD(poke, (std::ostream&, virtual_ptr<Animal>), void);
|
||||
}
|
||||
#else
|
||||
|
||||
// tag::friend[]
|
||||
namespace pets {
|
||||
struct Cat;
|
||||
struct Dog;
|
||||
template<typename> struct BOOST_OPENMETHOD_OVERRIDERS(poke);
|
||||
} // namespace pets
|
||||
|
||||
namespace core {
|
||||
class Animal {
|
||||
public:
|
||||
Animal(std::string name) : name(name) {
|
||||
}
|
||||
virtual ~Animal() = default;
|
||||
// end::friend[]
|
||||
|
||||
// tag::friend[]
|
||||
// ...
|
||||
private:
|
||||
std::string name;
|
||||
|
||||
friend struct BOOST_OPENMETHOD_OVERRIDERS(pets::poke)<
|
||||
void(std::ostream&, virtual_ptr<pets::Cat>)>;
|
||||
friend struct BOOST_OPENMETHOD_OVERRIDERS(pets::poke)<
|
||||
void(std::ostream&, virtual_ptr<pets::Dog>)>;
|
||||
};
|
||||
|
||||
BOOST_OPENMETHOD(poke, (std::ostream&, virtual_ptr<Animal>), void);
|
||||
}
|
||||
|
||||
// end::friend[]
|
||||
#endif
|
||||
|
||||
// tag::friend[]
|
||||
namespace pets {
|
||||
|
||||
struct Cat : core::Animal {
|
||||
using Animal::Animal;
|
||||
};
|
||||
|
||||
struct Dog : core::Animal {
|
||||
using Animal::Animal;
|
||||
};
|
||||
|
||||
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<Dog> dog), void) {
|
||||
os << dog->name << " barks";
|
||||
}
|
||||
|
||||
BOOST_OPENMETHOD_CLASSES(core::Animal, Cat, Dog);
|
||||
} // namespace pets
|
||||
// end::friend[]
|
||||
|
||||
#include <boost/openmethod/compiler.hpp>
|
||||
|
||||
int main() {
|
||||
boost::openmethod::initialize();
|
||||
|
||||
std::unique_ptr<core::Animal> a(new pets::Cat("Felix"));
|
||||
std::unique_ptr<core::Animal> b(new pets::Dog("Snoopy"));
|
||||
|
||||
core::poke(std::cout, *a); // Felix hisses
|
||||
std::cout << ".\n";
|
||||
|
||||
core::poke(std::cout, *b); // Snoopy barks
|
||||
std::cout << ".\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user