Merge branch 'master' into sf-re-use-heap-in-getNetworkDistance

This commit is contained in:
Siarhei Fedartsou 2024-05-26 11:55:18 +02:00
commit 49cf294d2f
115 changed files with 10916 additions and 10231 deletions

View File

@ -54,6 +54,7 @@ Checks: >
performance-*, performance-*,
-performance-noexcept-move-constructor, -performance-noexcept-move-constructor,
-performance-no-int-to-ptr, -performance-no-int-to-ptr,
-performance-type-promotion-in-math-fn,
readability-*, readability-*,
-readability-avoid-const-params-in-decls, -readability-avoid-const-params-in-decls,
-readability-braces-around-statements, -readability-braces-around-statements,
@ -82,6 +83,7 @@ Checks: >
-readability-make-member-function-const, -readability-make-member-function-const,
-readability-redundant-string-init, -readability-redundant-string-init,
-readability-non-const-parameter, -readability-non-const-parameter,
-readability-container-contains,
-readability-static-accessed-through-instance -readability-static-accessed-through-instance
WarningsAsErrors: '*' WarningsAsErrors: '*'

View File

@ -31,11 +31,11 @@ jobs:
env: env:
BUILD_TYPE: Release BUILD_TYPE: Release
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- run: pip install "conan<2.0.0" - run: pip install "conan<2.0.0"
- run: conan --version - run: conan --version
- run: cmake --version - run: cmake --version
- uses: actions/setup-node@v3 - uses: actions/setup-node@v4
with: with:
node-version: 18 node-version: 18
- run: node --version - run: node --version
@ -47,7 +47,7 @@ jobs:
echo PUBLISH=$([[ "${GITHUB_REF:-}" == "refs/tags/v${PACKAGE_JSON_VERSION}" ]] && echo "On" || echo "Off") >> $GITHUB_ENV echo PUBLISH=$([[ "${GITHUB_REF:-}" == "refs/tags/v${PACKAGE_JSON_VERSION}" ]] && echo "On" || echo "Off") >> $GITHUB_ENV
- run: npm install --ignore-scripts - run: npm install --ignore-scripts
- run: npm link --ignore-scripts - run: npm link --ignore-scripts
- uses: microsoft/setup-msbuild@v1.1 - uses: microsoft/setup-msbuild@v2
- name: Build - name: Build
run: | run: |
.\scripts\ci\windows-build.bat .\scripts\ci\windows-build.bat
@ -76,13 +76,13 @@ jobs:
format-taginfo-docs: format-taginfo-docs:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Use Node.js - name: Use Node.js
uses: actions/setup-node@v3 uses: actions/setup-node@v4
with: with:
node-version: 18 node-version: 18
- name: Enable Node.js cache - name: Enable Node.js cache
uses: actions/cache@v3 uses: actions/cache@v4
with: with:
path: ~/.npm path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
@ -106,9 +106,9 @@ jobs:
continue-on-error: false continue-on-error: false
steps: steps:
- name: Check out the repo - name: Check out the repo
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Enable osm.pbf cache - name: Enable osm.pbf cache
uses: actions/cache@v3 uses: actions/cache@v4
with: with:
path: berlin-latest.osm.pbf path: berlin-latest.osm.pbf
key: v1-berlin-osm-pbf key: v1-berlin-osm-pbf
@ -342,36 +342,36 @@ jobs:
OSRM_CONNECTION_RETRIES: ${{ matrix.OSRM_CONNECTION_RETRIES }} OSRM_CONNECTION_RETRIES: ${{ matrix.OSRM_CONNECTION_RETRIES }}
OSRM_CONNECTION_EXP_BACKOFF_COEF: ${{ matrix.OSRM_CONNECTION_EXP_BACKOFF_COEF }} OSRM_CONNECTION_EXP_BACKOFF_COEF: ${{ matrix.OSRM_CONNECTION_EXP_BACKOFF_COEF }}
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Build machine architecture - name: Build machine architecture
run: uname -m run: uname -m
- name: Use Node.js - name: Use Node.js
uses: actions/setup-node@v3 uses: actions/setup-node@v4
with: with:
node-version: ${{ matrix.node }} node-version: ${{ matrix.node }}
- name: Enable Node.js cache - name: Enable Node.js cache
uses: actions/cache@v3 uses: actions/cache@v4
with: with:
path: ~/.npm path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: | restore-keys: |
${{ runner.os }}-node- ${{ runner.os }}-node-
- name: Enable compiler cache - name: Enable compiler cache
uses: actions/cache@v3 uses: actions/cache@v4
with: with:
path: ~/.ccache path: ~/.ccache
key: ccache-${{ matrix.name }}-${{ github.sha }} key: ccache-${{ matrix.name }}-${{ github.sha }}
restore-keys: | restore-keys: |
ccache-${{ matrix.name }}- ccache-${{ matrix.name }}-
- name: Enable Conan cache - name: Enable Conan cache
uses: actions/cache@v3 uses: actions/cache@v4
with: with:
path: ~/.conan path: ~/.conan
key: v9-conan-${{ matrix.name }}-${{ github.sha }} key: v9-conan-${{ matrix.name }}-${{ github.sha }}
restore-keys: | restore-keys: |
v9-conan-${{ matrix.name }}- v9-conan-${{ matrix.name }}-
- name: Enable test cache - name: Enable test cache
uses: actions/cache@v3 uses: actions/cache@v4
with: with:
path: ${{github.workspace}}/test/cache path: ${{github.workspace}}/test/cache
key: v4-test-${{ matrix.name }}-${{ github.sha }} key: v4-test-${{ matrix.name }}-${{ github.sha }}
@ -396,6 +396,35 @@ jobs:
elif [[ "${RUNNER_OS}" == "macOS" ]]; then elif [[ "${RUNNER_OS}" == "macOS" ]]; then
echo "JOBS=$((`sysctl -n hw.ncpu` + 1))" >> $GITHUB_ENV echo "JOBS=$((`sysctl -n hw.ncpu` + 1))" >> $GITHUB_ENV
fi fi
# See: https://github.com/actions/toolkit/issues/946#issuecomment-1590016041
# We need it to be able to access system folders while restoring cached Boost below
- name: Give tar root ownership
if: runner.os == 'Linux' && matrix.ENABLE_CONAN != 'ON'
run: sudo chown root /bin/tar && sudo chmod u+s /bin/tar
- name: Cache Boost
if: runner.os == 'Linux' && matrix.ENABLE_CONAN != 'ON'
id: cache-boost
uses: actions/cache@v4
with:
path: |
/usr/local/include/boost
/usr/local/lib/libboost*
key: v1-boost-${{ runner.os }}-${{ runner.arch }}-${{ matrix.runs-on }}
restore-keys: |
v1-boost-${{ runner.os }}-${{ runner.arch }}-${{ matrix.runs-on }}
- name: Install Boost
if: steps.cache-boost.outputs.cache-hit != 'true' && runner.os == 'Linux' && matrix.ENABLE_CONAN != 'ON'
run: |
BOOST_VERSION="1.85.0"
BOOST_VERSION_UNDERSCORE="${BOOST_VERSION//./_}"
wget -q https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VERSION}/source/boost_${BOOST_VERSION_UNDERSCORE}.tar.gz
tar xzf boost_${BOOST_VERSION_UNDERSCORE}.tar.gz
cd boost_${BOOST_VERSION_UNDERSCORE}
sudo ./bootstrap.sh
sudo ./b2 install
cd ..
sudo rm -rf boost_${BOOST_VERSION_UNDERSCORE}*
- name: Install dev dependencies - name: Install dev dependencies
run: | run: |
@ -417,7 +446,7 @@ jobs:
# Linux dev packages # Linux dev packages
if [ "${ENABLE_CONAN}" != "ON" ]; then if [ "${ENABLE_CONAN}" != "ON" ]; then
sudo apt-get update -y sudo apt-get update -y
sudo apt-get install -y libbz2-dev libxml2-dev libzip-dev liblua5.2-dev libboost-all-dev sudo apt-get install -y libbz2-dev libxml2-dev libzip-dev liblua5.2-dev
if [[ "${CCOMPILER}" != clang-* ]]; then if [[ "${CCOMPILER}" != clang-* ]]; then
sudo apt-get install -y ${CXXCOMPILER} sudo apt-get install -y ${CXXCOMPILER}
fi fi
@ -511,7 +540,7 @@ jobs:
- name: Use Node 18 - name: Use Node 18
if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY == 'ON' }} if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY == 'ON' }}
uses: actions/setup-node@v3 uses: actions/setup-node@v4
with: with:
node-version: 18 node-version: 18
- name: Run Node package tests on Node 18 - name: Run Node package tests on Node 18
@ -521,7 +550,7 @@ jobs:
npm run nodejs-tests npm run nodejs-tests
- name: Use Node 20 - name: Use Node 20
if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY == 'ON' }} if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY == 'ON' }}
uses: actions/setup-node@v3 uses: actions/setup-node@v4
with: with:
node-version: 20 node-version: 20
- name: Run Node package tests on Node 20 - name: Run Node package tests on Node 20
@ -531,7 +560,7 @@ jobs:
npm run nodejs-tests npm run nodejs-tests
- name: Use Node latest - name: Use Node latest
if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY == 'ON' }} if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY == 'ON' }}
uses: actions/setup-node@v3 uses: actions/setup-node@v4
with: with:
node-version: latest node-version: latest
- name: Run Node package tests on Node-latest - name: Run Node package tests on Node-latest
@ -541,7 +570,7 @@ jobs:
npm run nodejs-tests npm run nodejs-tests
- name: Upload test logs - name: Upload test logs
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
if: failure() if: failure()
with: with:
name: logs name: logs
@ -557,7 +586,7 @@ jobs:
# # Uploading report to CodeCov # # Uploading report to CodeCov
# - name: Upload code coverage # - name: Upload code coverage
# if: ${{ matrix.ENABLE_COVERAGE == 'ON' }} # if: ${{ matrix.ENABLE_COVERAGE == 'ON' }}
# uses: codecov/codecov-action@v1 # uses: codecov/codecov-action@v4
# with: # with:
# files: coverage.info # files: coverage.info
# name: codecov-osrm-backend # name: codecov-osrm-backend
@ -595,21 +624,21 @@ jobs:
GITHUB_REPOSITORY: ${{ github.repository }} GITHUB_REPOSITORY: ${{ github.repository }}
steps: steps:
- name: Enable compiler cache - name: Enable compiler cache
uses: actions/cache@v3 uses: actions/cache@v4
with: with:
path: ~/.ccache path: ~/.ccache
key: v1-ccache-benchmarks-${{ github.sha }} key: v1-ccache-benchmarks-${{ github.sha }}
restore-keys: | restore-keys: |
v1-ccache-benchmarks- v1-ccache-benchmarks-
- name: Enable Conan cache - name: Enable Conan cache
uses: actions/cache@v3 uses: actions/cache@v4
with: with:
path: ~/.conan path: ~/.conan
key: v1-conan-benchmarks-${{ github.sha }} key: v1-conan-benchmarks-${{ github.sha }}
restore-keys: | restore-keys: |
v1-conan-benchmarks- v1-conan-benchmarks-
- name: Checkout PR Branch - name: Checkout PR Branch
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
ref: ${{ github.head_ref }} ref: ${{ github.head_ref }}
path: pr path: pr
@ -624,7 +653,7 @@ jobs:
cd .. cd ..
make -C test/data make -C test/data
- name: Checkout Base Branch - name: Checkout Base Branch
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
ref: ${{ github.event.pull_request.base.ref }} ref: ${{ github.event.pull_request.base.ref }}
path: base path: base

View File

@ -7,6 +7,8 @@
- ADDED: Add support for opposite approach request parameter. [#6842](https://github.com/Project-OSRM/osrm-backend/pull/6842) - ADDED: Add support for opposite approach request parameter. [#6842](https://github.com/Project-OSRM/osrm-backend/pull/6842)
- ADDED: Add support for accessing edge flags in `process_segment` [#6658](https://github.com/Project-OSRM/osrm-backend/pull/6658) - ADDED: Add support for accessing edge flags in `process_segment` [#6658](https://github.com/Project-OSRM/osrm-backend/pull/6658)
- Build: - Build:
- CHANGED: Upgrade CI actions to latest versions [#6893](https://github.com/Project-OSRM/osrm-backend/pull/6893)
- CHANGED: Remove outdated warnings #6894 [#6894](https://github.com/Project-OSRM/osrm-backend/pull/6894)
- ADDED: Add CI job which builds OSRM with gcc 12. [#6455](https://github.com/Project-OSRM/osrm-backend/pull/6455) - ADDED: Add CI job which builds OSRM with gcc 12. [#6455](https://github.com/Project-OSRM/osrm-backend/pull/6455)
- CHANGED: Upgrade to clang-tidy 15. [#6439](https://github.com/Project-OSRM/osrm-backend/pull/6439) - CHANGED: Upgrade to clang-tidy 15. [#6439](https://github.com/Project-OSRM/osrm-backend/pull/6439)
- CHANGED: Update actions/cache to v3. [#6420](https://github.com/Project-OSRM/osrm-backend/pull/6420) - CHANGED: Update actions/cache to v3. [#6420](https://github.com/Project-OSRM/osrm-backend/pull/6420)
@ -19,6 +21,10 @@
- NodeJS: - NodeJS:
- CHANGED: Use node-api instead of NAN. [#6452](https://github.com/Project-OSRM/osrm-backend/pull/6452) - CHANGED: Use node-api instead of NAN. [#6452](https://github.com/Project-OSRM/osrm-backend/pull/6452)
- Misc: - Misc:
- CHANGED: Bump mapbox/variant to version 1.2.0 [#6898](https://github.com/Project-OSRM/osrm-backend/pull/6898)
- CHANGED: Avoid copy of std::function-based callback in path unpacking [#6895](https://github.com/Project-OSRM/osrm-backend/pull/6895)
- CHANGED: Replace boost::hash by std::hash [#6892](https://github.com/Project-OSRM/osrm-backend/pull/6892)
- CHANGED: Partial fix migration from boost::optional to std::optional [#6551](https://github.com/Project-OSRM/osrm-backend/issues/6551)
- CHANGED: Update Conan Boost version to 1.85.0. [#6868](https://github.com/Project-OSRM/osrm-backend/pull/6868) - CHANGED: Update Conan Boost version to 1.85.0. [#6868](https://github.com/Project-OSRM/osrm-backend/pull/6868)
- FIXED: Fix an error in a RouteParameters AnnotationsType operator overload. [#6646](https://github.com/Project-OSRM/osrm-backend/pull/6646) - FIXED: Fix an error in a RouteParameters AnnotationsType operator overload. [#6646](https://github.com/Project-OSRM/osrm-backend/pull/6646)
- ADDED: Add support for "unlimited" to be passed as a value for the default-radius and max-matching-radius flags. [#6599](https://github.com/Project-OSRM/osrm-backend/pull/6599) - ADDED: Add support for "unlimited" to be passed as a value for the default-radius and max-matching-radius flags. [#6599](https://github.com/Project-OSRM/osrm-backend/pull/6599)
@ -48,6 +54,7 @@
- FIXED: Remove force-loop checks for routes with u-turns [#6858](https://github.com/Project-OSRM/osrm-backend/pull/6858) - FIXED: Remove force-loop checks for routes with u-turns [#6858](https://github.com/Project-OSRM/osrm-backend/pull/6858)
- FIXED: Correctly check runtime search conditions for forcing routing steps [#6866](https://github.com/Project-OSRM/osrm-backend/pull/6866) - FIXED: Correctly check runtime search conditions for forcing routing steps [#6866](https://github.com/Project-OSRM/osrm-backend/pull/6866)
- Map Matching: - Map Matching:
- CHANGED: Optimise path distance calculation in MLD map matching even more. [#6884](https://github.com/Project-OSRM/osrm-backend/pull/6884)
- CHANGED: Optimise path distance calculation in MLD map matching. [#6876](https://github.com/Project-OSRM/osrm-backend/pull/6876) - CHANGED: Optimise path distance calculation in MLD map matching. [#6876](https://github.com/Project-OSRM/osrm-backend/pull/6876)
- CHANGED: Optimise R-tree queries in the case of map matching. [#6881](https://github.com/Project-OSRM/osrm-backend/pull/6876) - CHANGED: Optimise R-tree queries in the case of map matching. [#6881](https://github.com/Project-OSRM/osrm-backend/pull/6876)
- Debug tiles: - Debug tiles:

View File

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.18) cmake_minimum_required(VERSION 3.18)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_EXTENSIONS OFF)

View File

@ -50,9 +50,7 @@ add_warning(all)
add_warning(extra) add_warning(extra)
add_warning(pedantic) add_warning(pedantic)
add_warning(error) # treat all warnings as errors add_warning(error) # treat all warnings as errors
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
add_warning(strict-overflow=2)
elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
add_warning(strict-overflow=1) add_warning(strict-overflow=1)
endif() endif()
add_warning(suggest-override) add_warning(suggest-override)
@ -79,15 +77,10 @@ add_warning(sizeof-array-argument)
add_warning(switch-bool) add_warning(switch-bool)
add_warning(tautological-compare) add_warning(tautological-compare)
add_warning(trampolines) add_warning(trampolines)
no_warning(c++17-extensions) # these warnings are not enabled by default
# TODO: these warnings are not enabled by default, but we consider them as useful and good to enable in the future # no_warning(name-of-warning)
no_warning(implicit-int-conversion) no_warning(deprecated-comma-subscript)
no_warning(implicit-float-conversion) no_warning(comma-subscript)
no_warning(unused-member-function) no_warning(ambiguous-reversed-operator)
no_warning(old-style-cast) no_warning(restrict)
no_warning(non-virtual-dtor) no_warning(free-nonheap-object)
no_warning(float-conversion)
no_warning(sign-conversion)
no_warning(shorten-64-to-32)
no_warning(padded)
no_warning(missing-noreturn)

View File

@ -1,128 +0,0 @@
#ifndef ITERATOR_BASED_CRC32_H
#define ITERATOR_BASED_CRC32_H
#if defined(__x86_64__) && !defined(__MINGW64__)
#include <cpuid.h>
#endif
#include <boost/crc.hpp> // for boost::crc_32_type
#include <iterator>
namespace osrm::contractor
{
class IteratorbasedCRC32
{
public:
bool UsingHardware() const { return use_hardware_implementation; }
IteratorbasedCRC32() : crc(0) { use_hardware_implementation = DetectHardwareSupport(); }
template <class Iterator> unsigned operator()(Iterator iter, const Iterator end)
{
unsigned crc = 0;
while (iter != end)
{
using value_type = typename std::iterator_traits<Iterator>::value_type;
const char *data = reinterpret_cast<const char *>(&(*iter));
if (use_hardware_implementation)
{
crc = ComputeInHardware(data, sizeof(value_type));
}
else
{
crc = ComputeInSoftware(data, sizeof(value_type));
}
++iter;
}
return crc;
}
private:
bool DetectHardwareSupport() const
{
static const int sse42_bit = 0x00100000;
const unsigned ecx = cpuid();
const bool sse42_found = (ecx & sse42_bit) != 0;
return sse42_found;
}
unsigned ComputeInSoftware(const char *str, unsigned len)
{
crc_processor.process_bytes(str, len);
return crc_processor.checksum();
}
// adapted from http://byteworm.com/2010/10/13/crc32/
unsigned ComputeInHardware(const char *str, unsigned len)
{
#if defined(__x86_64__)
unsigned q = len / sizeof(unsigned);
unsigned r = len % sizeof(unsigned);
unsigned *p = (unsigned *)str;
// crc=0;
while (q--)
{
__asm__ __volatile__(".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
: "=S"(crc)
: "0"(crc), "c"(*p));
++p;
}
str = reinterpret_cast<char *>(p);
while (r--)
{
__asm__ __volatile__(".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
: "=S"(crc)
: "0"(crc), "c"(*str));
++str;
}
#else
(void)str;
(void)len;
#endif
return crc;
}
inline unsigned cpuid() const
{
unsigned eax = 0, ebx = 0, ecx = 0, edx = 0;
// on X64 this calls hardware cpuid(.) instr. otherwise a dummy impl.
__get_cpuid(1, &eax, &ebx, &ecx, &edx);
return ecx;
}
#if defined(__MINGW64__) || defined(_MSC_VER) || !defined(__x86_64__)
inline void __get_cpuid(int /*param*/,
unsigned * /*eax*/,
unsigned * /*ebx*/,
unsigned *ecx,
unsigned * /*edx*/) const
{
*ecx = 0;
}
#endif
boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> crc_processor;
unsigned crc;
bool use_hardware_implementation;
};
struct RangebasedCRC32
{
template <typename Iteratable> unsigned operator()(const Iteratable &iterable)
{
return crc32(std::begin(iterable), std::end(iterable));
}
bool UsingHardware() const { return crc32.UsingHardware(); }
private:
IteratorbasedCRC32 crc32;
};
} // namespace osrm::contractor
#endif /* ITERATOR_BASED_CRC32_H */

View File

@ -55,7 +55,7 @@ template <> class AlgorithmDataFacade<CH>
virtual EdgeID FindSmallestEdge(const NodeID edge_based_node_from, virtual EdgeID FindSmallestEdge(const NodeID edge_based_node_from,
const NodeID edge_based_node_to, const NodeID edge_based_node_to,
const std::function<bool(EdgeData)> filter) const = 0; const std::function<bool(const EdgeData &)> &filter) const = 0;
}; };
template <> class AlgorithmDataFacade<MLD> template <> class AlgorithmDataFacade<MLD>

View File

@ -130,9 +130,10 @@ class ContiguousInternalMemoryAlgorithmDataFacade<CH> : public datafacade::Algor
edge_based_node_from, edge_based_node_to, result); edge_based_node_from, edge_based_node_to, result);
} }
EdgeID FindSmallestEdge(const NodeID edge_based_node_from, EdgeID
FindSmallestEdge(const NodeID edge_based_node_from,
const NodeID edge_based_node_to, const NodeID edge_based_node_to,
std::function<bool(EdgeData)> filter) const override final const std::function<bool(const EdgeData &)> &filter) const override final
{ {
return m_query_graph.FindSmallestEdge(edge_based_node_from, edge_based_node_to, filter); return m_query_graph.FindSmallestEdge(edge_based_node_from, edge_based_node_to, filter);
} }

View File

@ -12,6 +12,8 @@
#include "osrm/coordinate.hpp" #include "osrm/coordinate.hpp"
#include <boost/optional.hpp>
#include <algorithm> #include <algorithm>
#include <cmath> #include <cmath>
#include <iterator> #include <iterator>

View File

@ -1,7 +1,6 @@
#ifndef OSRM_ENGINE_GUIDANCE_COLLAPSE_HPP #ifndef OSRM_ENGINE_GUIDANCE_COLLAPSE_HPP
#include "engine/guidance/route_step.hpp" #include "engine/guidance/route_step.hpp"
#include "util/attributes.hpp"
#include <type_traits> #include <type_traits>
#include <vector> #include <vector>
@ -12,16 +11,15 @@ namespace osrm::engine::guidance
// Multiple possible reasons can result in unnecessary/confusing instructions // Multiple possible reasons can result in unnecessary/confusing instructions
// Collapsing such turns into a single turn instruction, we give a clearer // Collapsing such turns into a single turn instruction, we give a clearer
// set of instructions that is not cluttered by unnecessary turns/name changes. // set of instructions that is not cluttered by unnecessary turns/name changes.
OSRM_ATTR_WARN_UNUSED [[nodiscard]] std::vector<RouteStep> collapseTurnInstructions(std::vector<RouteStep> steps);
std::vector<RouteStep> collapseTurnInstructions(std::vector<RouteStep> steps);
// Multiple possible reasons can result in unnecessary/confusing instructions // Multiple possible reasons can result in unnecessary/confusing instructions
// A prime example would be a segregated intersection. Turning around at this // A prime example would be a segregated intersection. Turning around at this
// intersection would result in two instructions to turn left. // intersection would result in two instructions to turn left.
// Collapsing such turns into a single turn instruction, we give a clearer // Collapsing such turns into a single turn instruction, we give a clearer
// set of instructions that is not cluttered by unnecessary turns/name changes. // set of instructions that is not cluttered by unnecessary turns/name changes.
OSRM_ATTR_WARN_UNUSED [[nodiscard]] std::vector<RouteStep>
std::vector<RouteStep> collapseSegregatedTurnInstructions(std::vector<RouteStep> steps); collapseSegregatedTurnInstructions(std::vector<RouteStep> steps);
// A combined turn is a set of two instructions that actually form a single turn, as far as we // A combined turn is a set of two instructions that actually form a single turn, as far as we
// perceive it. A u-turn consisting of two left turns is one such example. But there are also lots // perceive it. A u-turn consisting of two left turns is one such example. But there are also lots

View File

@ -3,7 +3,6 @@
#include "guidance/turn_instruction.hpp" #include "guidance/turn_instruction.hpp"
#include "engine/guidance/route_step.hpp" #include "engine/guidance/route_step.hpp"
#include "util/attributes.hpp"
#include "util/bearing.hpp" #include "util/bearing.hpp"
#include "util/guidance/name_announcements.hpp" #include "util/guidance/name_announcements.hpp"
@ -166,8 +165,7 @@ inline bool areSameSide(const RouteStep &lhs, const RouteStep &rhs)
} }
// do this after invalidating any steps to compress the step array again // do this after invalidating any steps to compress the step array again
OSRM_ATTR_WARN_UNUSED [[nodiscard]] inline std::vector<RouteStep> removeNoTurnInstructions(std::vector<RouteStep> steps)
inline std::vector<RouteStep> removeNoTurnInstructions(std::vector<RouteStep> steps)
{ {
// finally clean up the post-processed instructions. // finally clean up the post-processed instructions.
// Remove all invalid instructions from the set of instructions. // Remove all invalid instructions from the set of instructions.

View File

@ -1,10 +1,9 @@
#ifndef OSRM_ENGINE_GUIDANCE_LANE_PROCESSING_HPP_ #ifndef OSRM_ENGINE_GUIDANCE_LANE_PROCESSING_HPP_
#define OSRM_ENGINE_GUIDANCE_LANE_PROCESSING_HPP_ #define OSRM_ENGINE_GUIDANCE_LANE_PROCESSING_HPP_
#include <vector>
#include "engine/guidance/route_step.hpp" #include "engine/guidance/route_step.hpp"
#include "util/attributes.hpp"
#include <vector>
namespace osrm::engine::guidance namespace osrm::engine::guidance
{ {
@ -14,8 +13,8 @@ namespace osrm::engine::guidance
// we anticipate lane changes emitting only matching lanes early on. // we anticipate lane changes emitting only matching lanes early on.
// the second parameter describes the duration that we feel two segments need to be apart to count // the second parameter describes the duration that we feel two segments need to be apart to count
// as separate maneuvers. // as separate maneuvers.
OSRM_ATTR_WARN_UNUSED [[nodiscard]] std::vector<RouteStep>
std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps, anticipateLaneChange(std::vector<RouteStep> steps,
const double min_distance_needed_for_lane_change = 200); const double min_distance_needed_for_lane_change = 200);
} // namespace osrm::engine::guidance } // namespace osrm::engine::guidance

View File

@ -5,7 +5,6 @@
#include "engine/guidance/leg_geometry.hpp" #include "engine/guidance/leg_geometry.hpp"
#include "engine/guidance/route_step.hpp" #include "engine/guidance/route_step.hpp"
#include "engine/phantom_node.hpp" #include "engine/phantom_node.hpp"
#include "util/attributes.hpp"
#include <vector> #include <vector>
@ -13,8 +12,7 @@ namespace osrm::engine::guidance
{ {
// passed as none-reference to modify in-place and move out again // passed as none-reference to modify in-place and move out again
OSRM_ATTR_WARN_UNUSED [[nodiscard]] std::vector<RouteStep> handleRoundabouts(std::vector<RouteStep> steps);
std::vector<RouteStep> handleRoundabouts(std::vector<RouteStep> steps);
// trim initial/final segment of very short length. // trim initial/final segment of very short length.
// This function uses in/out parameter passing to modify both steps and geometry in place. // This function uses in/out parameter passing to modify both steps and geometry in place.
@ -24,23 +22,21 @@ std::vector<RouteStep> handleRoundabouts(std::vector<RouteStep> steps);
void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry); void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry);
// assign relative locations to depart/arrive instructions // assign relative locations to depart/arrive instructions
OSRM_ATTR_WARN_UNUSED [[nodiscard]] std::vector<RouteStep> assignRelativeLocations(std::vector<RouteStep> steps,
std::vector<RouteStep> assignRelativeLocations(std::vector<RouteStep> steps,
const LegGeometry &geometry, const LegGeometry &geometry,
const PhantomNode &source_node, const PhantomNode &source_node,
const PhantomNode &target_node); const PhantomNode &target_node);
// collapse suppressed instructions remaining into intersections array // collapse suppressed instructions remaining into intersections array
OSRM_ATTR_WARN_UNUSED [[nodiscard]] std::vector<RouteStep> buildIntersections(std::vector<RouteStep> steps);
std::vector<RouteStep> buildIntersections(std::vector<RouteStep> steps);
// postProcess will break the connection between the leg geometry // postProcess will break the connection between the leg geometry
// for which a segment is supposed to represent exactly the coordinates // for which a segment is supposed to represent exactly the coordinates
// between routing maneuvers and the route steps itself. // between routing maneuvers and the route steps itself.
// If required, we can get both in sync again using this function. // If required, we can get both in sync again using this function.
// Move in LegGeometry for modification in place. // Move in LegGeometry for modification in place.
OSRM_ATTR_WARN_UNUSED [[nodiscard]] LegGeometry resyncGeometry(LegGeometry leg_geometry,
LegGeometry resyncGeometry(LegGeometry leg_geometry, const std::vector<RouteStep> &steps); const std::vector<RouteStep> &steps);
/** /**
* Apply maneuver override relations to the selected route. * Apply maneuver override relations to the selected route.

View File

@ -2,7 +2,6 @@
#define OSRM_ENGINE_GUIDANCE_VERBOSITY_REDUCTION_HPP_ #define OSRM_ENGINE_GUIDANCE_VERBOSITY_REDUCTION_HPP_
#include "engine/guidance/route_step.hpp" #include "engine/guidance/route_step.hpp"
#include "util/attributes.hpp"
#include <vector> #include <vector>
@ -13,8 +12,7 @@ namespace osrm::engine::guidance
// to announce them. All these that are not collapsed into a single turn (think segregated // to announce them. All these that are not collapsed into a single turn (think segregated
// intersection) have to be checked for the length they are active in. If they are active for a // intersection) have to be checked for the length they are active in. If they are active for a
// short distance only, we don't announce them // short distance only, we don't announce them
OSRM_ATTR_WARN_UNUSED [[nodiscard]] std::vector<RouteStep> suppressShortNameSegments(std::vector<RouteStep> steps);
std::vector<RouteStep> suppressShortNameSegments(std::vector<RouteStep> steps);
} // namespace osrm::engine::guidance } // namespace osrm::engine::guidance

View File

@ -122,7 +122,7 @@ void routingStep(const DataFacade<Algorithm> &facade,
const EdgeWeight new_weight = reverseHeapNode->weight + heapNode.weight; const EdgeWeight new_weight = reverseHeapNode->weight + heapNode.weight;
if (new_weight < upper_bound) if (new_weight < upper_bound)
{ {
if (shouldForceStep(force_step_nodes, heapNode, reverseHeapNode.get()) || if (shouldForceStep(force_step_nodes, heapNode, *reverseHeapNode) ||
// in this case we are looking at a bi-directional way where the source // in this case we are looking at a bi-directional way where the source
// and target phantom are on the same edge based node // and target phantom are on the same edge based node
new_weight < EdgeWeight{0}) new_weight < EdgeWeight{0})

View File

@ -11,6 +11,7 @@
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <algorithm> #include <algorithm>
#include <boost/core/ignore_unused.hpp>
#include <iterator> #include <iterator>
#include <limits> #include <limits>
#include <tuple> #include <tuple>
@ -311,15 +312,16 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
const auto &cell = const auto &cell =
cells.GetCell(metric, level, partition.GetCell(level, heapNode.node)); cells.GetCell(metric, level, partition.GetCell(level, heapNode.node));
auto destination = cell.GetDestinationNodes().begin(); auto destination = cell.GetDestinationNodes().begin();
auto distance = [&]() -> auto auto distance = [&cell, node = heapNode.node ]() -> auto
{ {
if constexpr (IS_MAP_MATCHING) if constexpr (IS_MAP_MATCHING)
{ {
return cell.GetOutDistance(heapNode.node).begin(); return cell.GetOutDistance(node).begin();
} }
else else
{ {
boost::ignore_unused(cell, node);
return 0; return 0;
} }
} }
@ -346,7 +348,7 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
} }
} }
++destination; ++destination;
if (IS_MAP_MATCHING) if constexpr (IS_MAP_MATCHING)
{ {
++distance; ++distance;
} }
@ -358,15 +360,16 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
const auto &cell = const auto &cell =
cells.GetCell(metric, level, partition.GetCell(level, heapNode.node)); cells.GetCell(metric, level, partition.GetCell(level, heapNode.node));
auto source = cell.GetSourceNodes().begin(); auto source = cell.GetSourceNodes().begin();
auto distance = [&]() -> auto auto distance = [&cell, node = heapNode.node ]() -> auto
{ {
if constexpr (IS_MAP_MATCHING) if constexpr (IS_MAP_MATCHING)
{ {
return cell.GetInDistance(heapNode.node).begin(); return cell.GetInDistance(node).begin();
} }
else else
{ {
boost::ignore_unused(cell, node);
return 0; return 0;
} }
} }
@ -392,7 +395,7 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
} }
} }
++source; ++source;
if (IS_MAP_MATCHING) if constexpr (IS_MAP_MATCHING)
{ {
++distance; ++distance;
} }
@ -465,7 +468,7 @@ void routingStep(const DataFacade<Algorithm> &facade,
auto reverse_weight = reverseHeapNode->weight; auto reverse_weight = reverseHeapNode->weight;
auto path_weight = weight + reverse_weight; auto path_weight = weight + reverse_weight;
if (!shouldForceStep(force_step_nodes, heapNode, reverseHeapNode.get()) && if (!shouldForceStep(force_step_nodes, heapNode, *reverseHeapNode) &&
(path_weight >= EdgeWeight{0}) && (path_weight < path_upper_bound)) (path_weight >= EdgeWeight{0}) && (path_weight < path_upper_bound))
{ {
middle_node = heapNode.node; middle_node = heapNode.node;
@ -703,8 +706,7 @@ double getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
{ {
reverse_heap.Clear(); reverse_heap.Clear();
if (forward_heap.Empty()) if (forward_heap.empty()) {
{
if (source_phantom.IsValidForwardSource()) if (source_phantom.IsValidForwardSource())
{ {
forward_heap.Insert(source_phantom.forward_segment_id.id, forward_heap.Insert(source_phantom.forward_segment_id.id,
@ -724,6 +726,7 @@ double getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
} }
} }
if (target_phantom.IsValidForwardTarget()) if (target_phantom.IsValidForwardTarget())
{ {
reverse_heap.Insert( reverse_heap.Insert(

View File

@ -3,11 +3,9 @@
#include "extractor/class_data.hpp" #include "extractor/class_data.hpp"
#include "extractor/turn_lane_types.hpp" #include "extractor/turn_lane_types.hpp"
#include "util/std_hash.hpp"
#include "util/typedefs.hpp" #include "util/typedefs.hpp"
#include <boost/functional/hash.hpp>
#include <boost/optional/optional_fwd.hpp>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
@ -18,25 +16,6 @@ class Way;
class Relation; class Relation;
} // namespace osmium } // namespace osmium
namespace std
{
template <> struct hash<std::tuple<std::string, std::string, std::string, std::string, std::string>>
{
std::size_t operator()(
const std::tuple<std::string, std::string, std::string, std::string, std::string> &mk)
const noexcept
{
std::size_t seed = 0;
boost::hash_combine(seed, std::get<0>(mk));
boost::hash_combine(seed, std::get<1>(mk));
boost::hash_combine(seed, std::get<2>(mk));
boost::hash_combine(seed, std::get<3>(mk));
boost::hash_combine(seed, std::get<4>(mk));
return seed;
}
};
} // namespace std
namespace osrm::extractor namespace osrm::extractor
{ {

View File

@ -1,16 +1,15 @@
#ifndef OSRM_EXTRACTOR_INTERSECTION_COORDINATE_EXTRACTOR_HPP_ #ifndef OSRM_EXTRACTOR_INTERSECTION_COORDINATE_EXTRACTOR_HPP_
#define OSRM_EXTRACTOR_INTERSECTION_COORDINATE_EXTRACTOR_HPP_ #define OSRM_EXTRACTOR_INTERSECTION_COORDINATE_EXTRACTOR_HPP_
#include <utility>
#include <vector>
#include "extractor/compressed_edge_container.hpp" #include "extractor/compressed_edge_container.hpp"
#include "extractor/query_node.hpp" #include "extractor/query_node.hpp"
#include "util/attributes.hpp"
#include "util/coordinate.hpp" #include "util/coordinate.hpp"
#include "util/node_based_graph.hpp" #include "util/node_based_graph.hpp"
#include <utility>
#include <vector>
namespace osrm::extractor::intersection namespace osrm::extractor::intersection
{ {
@ -27,8 +26,8 @@ class CoordinateExtractor
* Note: The segment between intersection and turn coordinate can be zero, if the OSM modelling * Note: The segment between intersection and turn coordinate can be zero, if the OSM modelling
* is unfortunate. See https://github.com/Project-OSRM/osrm-backend/issues/3470 * is unfortunate. See https://github.com/Project-OSRM/osrm-backend/issues/3470
*/ */
OSRM_ATTR_WARN_UNUSED [[nodiscard]] util::Coordinate
util::Coordinate GetCoordinateAlongRoad(const NodeID intersection_node, GetCoordinateAlongRoad(const NodeID intersection_node,
const EdgeID turn_edge, const EdgeID turn_edge,
const bool traversed_in_reverse, const bool traversed_in_reverse,
const NodeID to_node, const NodeID to_node,
@ -36,8 +35,7 @@ class CoordinateExtractor
// Given a set of precomputed coordinates, select the representative coordinate along the road // Given a set of precomputed coordinates, select the representative coordinate along the road
// that best describes the turn // that best describes the turn
OSRM_ATTR_WARN_UNUSED [[nodiscard]] util::Coordinate
util::Coordinate
ExtractRepresentativeCoordinate(const NodeID intersection_node, ExtractRepresentativeCoordinate(const NodeID intersection_node,
const EdgeID turn_edge, const EdgeID turn_edge,
const bool traversed_in_reverse, const bool traversed_in_reverse,
@ -47,7 +45,7 @@ class CoordinateExtractor
// instead of finding only a single coordinate, we can also list all coordinates along a // instead of finding only a single coordinate, we can also list all coordinates along a
// road. // road.
OSRM_ATTR_WARN_UNUSED std::vector<util::Coordinate> [[nodiscard]] std::vector<util::Coordinate>
GetCoordinatesAlongRoad(const NodeID intersection_node, GetCoordinatesAlongRoad(const NodeID intersection_node,
const EdgeID turn_edge, const EdgeID turn_edge,
const bool traversed_in_reverse, const bool traversed_in_reverse,
@ -55,17 +53,15 @@ class CoordinateExtractor
// wrapper in case of normal forward edges (traversed_in_reverse = false, to_node = // wrapper in case of normal forward edges (traversed_in_reverse = false, to_node =
// node_based_graph.GetTarget(turn_edge) // node_based_graph.GetTarget(turn_edge)
OSRM_ATTR_WARN_UNUSED [[nodiscard]] std::vector<util::Coordinate>
std::vector<util::Coordinate> GetForwardCoordinatesAlongRoad(const NodeID from, GetForwardCoordinatesAlongRoad(const NodeID from, const EdgeID turn_edge) const;
const EdgeID turn_edge) const;
// a less precise way to compute coordinates along a route. Due to the heavy interaction of // a less precise way to compute coordinates along a route. Due to the heavy interaction of
// graph traversal and turn instructions, we often don't care for high precision. We only want // graph traversal and turn instructions, we often don't care for high precision. We only want
// to check for available connections in order, or find (with room for error) the straightmost // to check for available connections in order, or find (with room for error) the straightmost
// turn. This function will offer a bit more error potential but allow for much higher // turn. This function will offer a bit more error potential but allow for much higher
// performance // performance
OSRM_ATTR_WARN_UNUSED [[nodiscard]] util::Coordinate GetCoordinateCloseToTurn(const NodeID from_node,
util::Coordinate GetCoordinateCloseToTurn(const NodeID from_node,
const EdgeID turn_edge, const EdgeID turn_edge,
const bool traversed_in_reverse, const bool traversed_in_reverse,
const NodeID to_node) const; const NodeID to_node) const;
@ -90,22 +86,19 @@ class CoordinateExtractor
* The optional length cache needs to store the accumulated distance up to the respective * The optional length cache needs to store the accumulated distance up to the respective
* coordinate index [0,d(0,1),...] * coordinate index [0,d(0,1),...]
*/ */
OSRM_ATTR_WARN_UNUSED [[nodiscard]] std::vector<util::Coordinate>
std::vector<util::Coordinate>
TrimCoordinatesToLength(std::vector<util::Coordinate> coordinates, TrimCoordinatesToLength(std::vector<util::Coordinate> coordinates,
const double desired_length, const double desired_length,
const std::vector<double> &length_cache = {}) const; const std::vector<double> &length_cache = {}) const;
OSRM_ATTR_WARN_UNUSED [[nodiscard]] std::vector<double>
std::vector<double> PrepareLengthCache(const std::vector<util::Coordinate> &coordinates, PrepareLengthCache(const std::vector<util::Coordinate> &coordinates, const double limit) const;
const double limit) const;
/* when looking at a set of coordinates, this function allows trimming the vector to a smaller, /* when looking at a set of coordinates, this function allows trimming the vector to a smaller,
* only containing coordinates up to a given distance along the path. The last coordinate might * only containing coordinates up to a given distance along the path. The last coordinate might
* be interpolated * be interpolated
*/ */
OSRM_ATTR_WARN_UNUSED [[nodiscard]] std::vector<util::Coordinate>
std::vector<util::Coordinate>
TrimCoordinatesByLengthFront(std::vector<util::Coordinate> coordinates, TrimCoordinatesByLengthFront(std::vector<util::Coordinate> coordinates,
const double desired_length) const; const double desired_length) const;
@ -130,8 +123,7 @@ class CoordinateExtractor
* *
* for fixpoint `b`, vector_base `d` and vector_head `e` * for fixpoint `b`, vector_base `d` and vector_head `e`
*/ */
OSRM_ATTR_WARN_UNUSED [[nodiscard]] util::Coordinate GetCorrectedCoordinate(const util::Coordinate fixpoint,
util::Coordinate GetCorrectedCoordinate(const util::Coordinate fixpoint,
const util::Coordinate vector_base, const util::Coordinate vector_base,
const util::Coordinate vector_head) const; const util::Coordinate vector_head) const;
@ -143,8 +135,7 @@ class CoordinateExtractor
* Into: * Into:
* x -- x -- x -- x -- x - x * x -- x -- x -- x -- x - x
*/ */
OSRM_ATTR_WARN_UNUSED [[nodiscard]] std::vector<util::Coordinate>
std::vector<util::Coordinate>
SampleCoordinates(const std::vector<util::Coordinate> &coordinates, SampleCoordinates(const std::vector<util::Coordinate> &coordinates,
const double length, const double length,
const double rate) const; const double rate) const;

View File

@ -11,8 +11,8 @@
#include "util/typedefs.hpp" #include "util/typedefs.hpp"
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/optional.hpp>
#include <cstdint> #include <cstdint>
#include <optional>
#include <utility> #include <utility>
namespace osrm::extractor::intersection namespace osrm::extractor::intersection
@ -42,7 +42,7 @@ class NodeBasedGraphWalker
* selector not provinding any further edge to traverse) * selector not provinding any further edge to traverse)
*/ */
template <class accumulator_type, class selector_type> template <class accumulator_type, class selector_type>
boost::optional<std::pair<NodeID, EdgeID>> TraverseRoad(NodeID starting_at_node_id, std::optional<std::pair<NodeID, EdgeID>> TraverseRoad(NodeID starting_at_node_id,
EdgeID following_edge_id, EdgeID following_edge_id,
accumulator_type &accumulator, accumulator_type &accumulator,
const selector_type &selector) const; const selector_type &selector) const;
@ -111,7 +111,7 @@ struct SelectRoadByNameOnlyChoiceAndStraightness
* traversal. If no such edge is found, return {} is allowed. Usually you want to choose some * traversal. If no such edge is found, return {} is allowed. Usually you want to choose some
* form of obious turn to follow. * form of obious turn to follow.
*/ */
boost::optional<EdgeID> operator()(const NodeID nid, std::optional<EdgeID> operator()(const NodeID nid,
const EdgeID via_edge_id, const EdgeID via_edge_id,
const IntersectionView &intersection, const IntersectionView &intersection,
const util::NodeBasedDynamicGraph &node_based_graph, const util::NodeBasedDynamicGraph &node_based_graph,
@ -138,7 +138,7 @@ struct SelectStraightmostRoadByNameAndOnlyChoice
* traversal. If no such edge is found, return {} is allowed. Usually you want to choose some * traversal. If no such edge is found, return {} is allowed. Usually you want to choose some
* form of obious turn to follow. * form of obious turn to follow.
*/ */
boost::optional<EdgeID> operator()(const NodeID nid, std::optional<EdgeID> operator()(const NodeID nid,
const EdgeID via_edge_id, const EdgeID via_edge_id,
const IntersectionView &intersection, const IntersectionView &intersection,
const util::NodeBasedDynamicGraph &node_based_graph, const util::NodeBasedDynamicGraph &node_based_graph,
@ -187,7 +187,7 @@ struct IntersectionFinderAccumulator
}; };
template <class accumulator_type, class selector_type> template <class accumulator_type, class selector_type>
boost::optional<std::pair<NodeID, EdgeID>> std::optional<std::pair<NodeID, EdgeID>>
NodeBasedGraphWalker::TraverseRoad(NodeID current_node_id, NodeBasedGraphWalker::TraverseRoad(NodeID current_node_id,
EdgeID current_edge_id, EdgeID current_edge_id,
accumulator_type &accumulator, accumulator_type &accumulator,
@ -254,7 +254,7 @@ NodeBasedGraphWalker::TraverseRoad(NodeID current_node_id,
struct SkipTrafficSignalBarrierRoadSelector struct SkipTrafficSignalBarrierRoadSelector
{ {
boost::optional<EdgeID> operator()(const NodeID, std::optional<EdgeID> operator()(const NodeID,
const EdgeID, const EdgeID,
const IntersectionView &intersection, const IntersectionView &intersection,
const util::NodeBasedDynamicGraph &, const util::NodeBasedDynamicGraph &,
@ -262,11 +262,11 @@ struct SkipTrafficSignalBarrierRoadSelector
{ {
if (intersection.isTrafficSignalOrBarrier()) if (intersection.isTrafficSignalOrBarrier())
{ {
return boost::make_optional(intersection[1].eid); return std::make_optional(intersection[1].eid);
} }
else else
{ {
return boost::none; return std::nullopt;
} }
} }
}; };

View File

@ -8,11 +8,13 @@
#include "turn_path.hpp" #include "turn_path.hpp"
#include "util/integer_range.hpp" #include "util/integer_range.hpp"
#include "util/log.hpp" #include "util/log.hpp"
#include "util/std_hash.hpp"
#include "util/vector_view.hpp" #include "util/vector_view.hpp"
#include <algorithm>
#include <boost/functional/hash.hpp>
#include <mapbox/variant.hpp> #include <mapbox/variant.hpp>
#include <algorithm>
namespace osrm::extractor namespace osrm::extractor
{ {
@ -147,7 +149,6 @@ struct UnresolvedManeuverOverride
namespace std namespace std
{ {
template <> struct hash<osrm::extractor::NodeBasedTurn> template <> struct hash<osrm::extractor::NodeBasedTurn>
{ {
using argument_type = osrm::extractor::NodeBasedTurn; using argument_type = osrm::extractor::NodeBasedTurn;
using result_type = std::size_t; using result_type = std::size_t;
@ -155,9 +156,9 @@ template <> struct hash<osrm::extractor::NodeBasedTurn>
{ {
std::size_t seed = 0; std::size_t seed = 0;
boost::hash_combine(seed, s.from); hash_combine(seed, s.from);
boost::hash_combine(seed, s.via); hash_combine(seed, s.via);
boost::hash_combine(seed, s.to); hash_combine(seed, s.to);
return seed; return seed;
} }

View File

@ -3,7 +3,7 @@
#include "maneuver_override.hpp" #include "maneuver_override.hpp"
#include <boost/optional.hpp> #include <optional>
#include <string> #include <string>
#include <vector> #include <vector>
@ -55,7 +55,7 @@ class ManeuverOverrideRelationParser
{ {
public: public:
ManeuverOverrideRelationParser(); ManeuverOverrideRelationParser();
boost::optional<InputManeuverOverride> TryParse(const osmium::Relation &relation) const; std::optional<InputManeuverOverride> TryParse(const osmium::Relation &relation) const;
}; };
} // namespace osrm::extractor } // namespace osrm::extractor

View File

@ -7,11 +7,11 @@
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/numeric/conversion/cast.hpp> #include <boost/numeric/conversion/cast.hpp>
#include <boost/optional.hpp>
#include <algorithm> #include <algorithm>
#include <array> #include <array>
#include <cstdint> #include <cstdint>
#include <optional>
namespace osrm::extractor namespace osrm::extractor
{ {
@ -80,7 +80,7 @@ struct ProfileProperties
} }
// Check if this classes are excludable // Check if this classes are excludable
boost::optional<std::size_t> ClassesAreExcludable(ClassData classes) const std::optional<std::size_t> ClassesAreExcludable(ClassData classes) const
{ {
auto iter = std::find(excludable_classes.begin(), excludable_classes.end(), classes); auto iter = std::find(excludable_classes.begin(), excludable_classes.end(), classes);
if (iter != excludable_classes.end()) if (iter != excludable_classes.end())

View File

@ -1,10 +1,11 @@
#ifndef OSRM_EXTRACTOR_TRAFFIC_SIGNALS_HPP #ifndef OSRM_EXTRACTOR_TRAFFIC_SIGNALS_HPP
#define OSRM_EXTRACTOR_TRAFFIC_SIGNALS_HPP #define OSRM_EXTRACTOR_TRAFFIC_SIGNALS_HPP
#include "util/std_hash.hpp"
#include "util/typedefs.hpp" #include "util/typedefs.hpp"
#include <boost/functional/hash.hpp>
#include <unordered_set> #include <unordered_set>
#include <utility>
namespace osrm::extractor namespace osrm::extractor
{ {
@ -12,8 +13,7 @@ namespace osrm::extractor
struct TrafficSignals struct TrafficSignals
{ {
std::unordered_set<NodeID> bidirectional_nodes; std::unordered_set<NodeID> bidirectional_nodes;
std::unordered_set<std::pair<NodeID, NodeID>, boost::hash<std::pair<NodeID, NodeID>>> std::unordered_set<std::pair<NodeID, NodeID>> unidirectional_segments;
unidirectional_segments;
inline bool HasSignal(NodeID from, NodeID to) const inline bool HasSignal(NodeID from, NodeID to) const
{ {

View File

@ -3,10 +3,9 @@
#include "util/concurrent_id_map.hpp" #include "util/concurrent_id_map.hpp"
#include "util/integer_range.hpp" #include "util/integer_range.hpp"
#include "util/std_hash.hpp"
#include "util/typedefs.hpp" #include "util/typedefs.hpp"
#include <boost/functional/hash.hpp>
#include <bitset> #include <bitset>
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
@ -54,19 +53,7 @@ const constexpr Mask merge_to_right = 1u << 10u;
using TurnLaneDescription = std::vector<TurnLaneType::Mask>; using TurnLaneDescription = std::vector<TurnLaneType::Mask>;
// hash function for TurnLaneDescription using LaneDescriptionMap = util::ConcurrentIDMap<TurnLaneDescription, LaneDescriptionID>;
struct TurnLaneDescription_hash
{
std::size_t operator()(const TurnLaneDescription &lane_description) const
{
std::size_t seed = 0;
boost::hash_range(seed, lane_description.begin(), lane_description.end());
return seed;
}
};
using LaneDescriptionMap =
util::ConcurrentIDMap<TurnLaneDescription, LaneDescriptionID, TurnLaneDescription_hash>;
using TurnLanesIndexedArray = using TurnLanesIndexedArray =
std::tuple<std::vector<std::uint32_t>, std::vector<TurnLaneType::Mask>>; std::tuple<std::vector<std::uint32_t>, std::vector<TurnLaneType::Mask>>;

View File

@ -15,11 +15,10 @@
#include <algorithm> #include <algorithm>
#include <cstddef> #include <cstddef>
#include <optional>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include <boost/optional.hpp>
namespace osrm::guidance namespace osrm::guidance
{ {
@ -129,7 +128,7 @@ class IntersectionHandler
// ^ via // ^ via
// //
// For this scenario returns intersection at `b` and `b`. // For this scenario returns intersection at `b` and `b`.
boost::optional<IntersectionHandler::IntersectionViewAndNode> std::optional<IntersectionHandler::IntersectionViewAndNode>
getNextIntersection(const NodeID at, const EdgeID via) const; getNextIntersection(const NodeID at, const EdgeID via) const;
bool isSameName(const EdgeID source_edge_id, const EdgeID target_edge_id) const; bool isSameName(const EdgeID source_edge_id, const EdgeID target_edge_id) const;

View File

@ -7,7 +7,6 @@
#include "guidance/intersection_handler.hpp" #include "guidance/intersection_handler.hpp"
#include "guidance/is_through_street.hpp" #include "guidance/is_through_street.hpp"
#include "util/attributes.hpp"
#include "util/node_based_graph.hpp" #include "util/node_based_graph.hpp"
#include <vector> #include <vector>
@ -42,18 +41,14 @@ class MotorwayHandler final : public IntersectionHandler
Intersection intersection) const override final; Intersection intersection) const override final;
private: private:
OSRM_ATTR_WARN_UNUSED [[nodiscard]] Intersection handleSliproads(const NodeID intersection_node_id,
Intersection handleSliproads(const NodeID intersection_node_id,
Intersection intersection) const; Intersection intersection) const;
OSRM_ATTR_WARN_UNUSED [[nodiscard]] Intersection fromMotorway(const EdgeID via_edge, Intersection intersection) const;
Intersection fromMotorway(const EdgeID via_edge, Intersection intersection) const;
OSRM_ATTR_WARN_UNUSED [[nodiscard]] Intersection fromRamp(const EdgeID via_edge, Intersection intersection) const;
Intersection fromRamp(const EdgeID via_edge, Intersection intersection) const;
OSRM_ATTR_WARN_UNUSED [[nodiscard]] Intersection fallback(Intersection intersection) const;
Intersection fallback(Intersection intersection) const;
}; };
} // namespace osrm::guidance } // namespace osrm::guidance

View File

@ -7,8 +7,6 @@
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/tokenizer.hpp> #include <boost/tokenizer.hpp>
#include "util/attributes.hpp"
namespace osrm::extractor::guidance namespace osrm::extractor::guidance
{ {
@ -21,8 +19,7 @@ namespace osrm::extractor::guidance
// will be corrected to left|throught, since the final lane is not drivable. // will be corrected to left|throught, since the final lane is not drivable.
// This is in contrast to a situation with lanes:psv:forward=0 (or not set) where left|through| // This is in contrast to a situation with lanes:psv:forward=0 (or not set) where left|through|
// represents left|through|through // represents left|through|through
OSRM_ATTR_WARN_UNUSED [[nodiscard]] inline std::string
inline std::string
trimLaneString(std::string lane_string, std::int32_t count_left, std::int32_t count_right) trimLaneString(std::string lane_string, std::int32_t count_left, std::int32_t count_right)
{ {
if (count_left) if (count_left)
@ -68,8 +65,8 @@ trimLaneString(std::string lane_string, std::int32_t count_left, std::int32_t co
// turn:lanes=left|through|through|right // turn:lanes=left|through|through|right
// vehicle:lanes=yes|yes|no|yes // vehicle:lanes=yes|yes|no|yes
// bicycle:lanes=yes|no|designated|yes // bicycle:lanes=yes|no|designated|yes
OSRM_ATTR_WARN_UNUSED [[nodiscard]] inline std::string applyAccessTokens(std::string lane_string,
inline std::string applyAccessTokens(std::string lane_string, const std::string &access_tokens) const std::string &access_tokens)
{ {
using tokenizer = boost::tokenizer<boost::char_separator<char>>; using tokenizer = boost::tokenizer<boost::char_separator<char>>;
boost::char_separator<char> sep("|", "", boost::keep_empty_tokens); boost::char_separator<char> sep("|", "", boost::keep_empty_tokens);

View File

@ -9,10 +9,9 @@
#include "util/node_based_graph.hpp" #include "util/node_based_graph.hpp"
#include <optional>
#include <vector> #include <vector>
#include <boost/optional.hpp>
namespace osrm::guidance namespace osrm::guidance
{ {
@ -43,7 +42,7 @@ class SliproadHandler final : public IntersectionHandler
Intersection intersection) const override final; Intersection intersection) const override final;
private: private:
boost::optional<std::size_t> getObviousIndexWithSliproads(const EdgeID from, std::optional<std::size_t> getObviousIndexWithSliproads(const EdgeID from,
const Intersection &intersection, const Intersection &intersection,
const NodeID at) const; const NodeID at) const;

View File

@ -17,7 +17,6 @@
#include "guidance/turn_classification.hpp" #include "guidance/turn_classification.hpp"
#include "guidance/turn_handler.hpp" #include "guidance/turn_handler.hpp"
#include "util/attributes.hpp"
#include "util/node_based_graph.hpp" #include "util/node_based_graph.hpp"
#include <cstdint> #include <cstdint>
@ -47,13 +46,11 @@ class TurnAnalysis
/* Full Analysis Process for a single node/edge combination. Use with caution, as the process is /* Full Analysis Process for a single node/edge combination. Use with caution, as the process is
* relatively expensive */ * relatively expensive */
OSRM_ATTR_WARN_UNUSED [[nodiscard]] Intersection operator()(const NodeID node_prior_to_intersection,
Intersection operator()(const NodeID node_prior_to_intersection,
const EdgeID entering_via_edge) const; const EdgeID entering_via_edge) const;
// Select turn types based on the intersection shape // Select turn types based on the intersection shape
OSRM_ATTR_WARN_UNUSED [[nodiscard]] Intersection
Intersection
AssignTurnTypes(const NodeID from_node, AssignTurnTypes(const NodeID from_node,
const EdgeID via_eid, const EdgeID via_eid,
const extractor::intersection::IntersectionView &intersection) const; const extractor::intersection::IntersectionView &intersection) const;

View File

@ -8,12 +8,10 @@
#include "guidance/intersection_handler.hpp" #include "guidance/intersection_handler.hpp"
#include "guidance/is_through_street.hpp" #include "guidance/is_through_street.hpp"
#include "util/attributes.hpp"
#include "util/node_based_graph.hpp" #include "util/node_based_graph.hpp"
#include <boost/optional.hpp>
#include <cstddef> #include <cstddef>
#include <optional>
#include <utility> #include <utility>
#include <vector> #include <vector>
@ -72,39 +70,36 @@ class TurnHandler final : public IntersectionHandler
bool hasObvious(const EdgeID &via_edge, const Fork &fork) const; bool hasObvious(const EdgeID &via_edge, const Fork &fork) const;
boost::optional<Fork> findForkCandidatesByGeometry(Intersection &intersection) const; std::optional<Fork> findForkCandidatesByGeometry(Intersection &intersection) const;
bool isCompatibleByRoadClass(const Intersection &intersection, const Fork fork) const; bool isCompatibleByRoadClass(const Intersection &intersection, const Fork fork) const;
// Dead end. // Dead end.
OSRM_ATTR_WARN_UNUSED [[nodiscard]] Intersection handleOneWayTurn(Intersection intersection) const;
Intersection handleOneWayTurn(Intersection intersection) const;
// Mode Changes, new names... // Mode Changes, new names...
OSRM_ATTR_WARN_UNUSED [[nodiscard]] Intersection handleTwoWayTurn(const EdgeID via_edge,
Intersection handleTwoWayTurn(const EdgeID via_edge, Intersection intersection) const; Intersection intersection) const;
// Forks, T intersections and similar // Forks, T intersections and similar
OSRM_ATTR_WARN_UNUSED [[nodiscard]] Intersection handleThreeWayTurn(const EdgeID via_edge,
Intersection handleThreeWayTurn(const EdgeID via_edge, Intersection intersection) const; Intersection intersection) const;
// Handling of turns larger then degree three // Handling of turns larger then degree three
OSRM_ATTR_WARN_UNUSED [[nodiscard]] Intersection handleComplexTurn(const EdgeID via_edge,
Intersection handleComplexTurn(const EdgeID via_edge, Intersection intersection) const; Intersection intersection) const;
void void
handleDistinctConflict(const EdgeID via_edge, ConnectedRoad &left, ConnectedRoad &right) const; handleDistinctConflict(const EdgeID via_edge, ConnectedRoad &left, ConnectedRoad &right) const;
// Classification // Classification
boost::optional<Fork> findFork(const EdgeID via_edge, Intersection &intersection) const; std::optional<Fork> findFork(const EdgeID via_edge, Intersection &intersection) const;
OSRM_ATTR_WARN_UNUSED [[nodiscard]] Intersection assignLeftTurns(const EdgeID via_edge,
Intersection assignLeftTurns(const EdgeID via_edge,
Intersection intersection, Intersection intersection,
const std::size_t starting_at) const; const std::size_t starting_at) const;
OSRM_ATTR_WARN_UNUSED [[nodiscard]] Intersection assignRightTurns(const EdgeID via_edge,
Intersection assignRightTurns(const EdgeID via_edge,
Intersection intersection, Intersection intersection,
const std::size_t up_to) const; const std::size_t up_to) const;
}; };

View File

@ -2,7 +2,6 @@
#define OSRM_GUIDANCE_TURN_INSTRUCTION_HPP_ #define OSRM_GUIDANCE_TURN_INSTRUCTION_HPP_
#include "guidance/roundabout_type.hpp" #include "guidance/roundabout_type.hpp"
#include "util/attributes.hpp"
#include "util/typedefs.hpp" #include "util/typedefs.hpp"
#include <algorithm> #include <algorithm>
@ -243,8 +242,7 @@ inline guidance::DirectionModifier::Enum getTurnDirection(const double angle)
} }
// swaps left <-> right modifier types // swaps left <-> right modifier types
OSRM_ATTR_WARN_UNUSED [[nodiscard]] inline guidance::DirectionModifier::Enum
inline guidance::DirectionModifier::Enum
mirrorDirectionModifier(const guidance::DirectionModifier::Enum modifier) mirrorDirectionModifier(const guidance::DirectionModifier::Enum modifier)
{ {
const constexpr guidance::DirectionModifier::Enum results[] = { const constexpr guidance::DirectionModifier::Enum results[] = {

View File

@ -3,13 +3,11 @@
#include "guidance/intersection.hpp" #include "guidance/intersection.hpp"
#include "guidance/turn_lane_data.hpp" #include "guidance/turn_lane_data.hpp"
#include "util/attributes.hpp"
namespace osrm::guidance::lanes namespace osrm::guidance::lanes
{ {
OSRM_ATTR_WARN_UNUSED [[nodiscard]] LaneDataVector handleNoneValueAtSimpleTurn(LaneDataVector lane_data,
LaneDataVector handleNoneValueAtSimpleTurn(LaneDataVector lane_data,
const Intersection &intersection); const Intersection &intersection);
} // namespace osrm::guidance::lanes } // namespace osrm::guidance::lanes

View File

@ -2,7 +2,6 @@
#define OSRM_GUIDANCE_TURN_LANE_DATA_HPP_ #define OSRM_GUIDANCE_TURN_LANE_DATA_HPP_
#include "extractor/turn_lane_types.hpp" #include "extractor/turn_lane_types.hpp"
#include "util/attributes.hpp"
#include "util/typedefs.hpp" #include "util/typedefs.hpp"
#include <vector> #include <vector>
@ -23,8 +22,8 @@ struct TurnLaneData
using LaneDataVector = std::vector<TurnLaneData>; using LaneDataVector = std::vector<TurnLaneData>;
// convertes a string given in the OSM format into a TurnLaneData vector // convertes a string given in the OSM format into a TurnLaneData vector
OSRM_ATTR_WARN_UNUSED [[nodiscard]] LaneDataVector
LaneDataVector laneDataFromDescription(const extractor::TurnLaneDescription &turn_lane_description); laneDataFromDescription(const extractor::TurnLaneDescription &turn_lane_description);
// Locate A Tag in a lane data vector (if multiple tags are set, the first one found is returned) // Locate A Tag in a lane data vector (if multiple tags are set, the first one found is returned)
LaneDataVector::const_iterator findTag(const extractor::TurnLaneType::Mask tag, LaneDataVector::const_iterator findTag(const extractor::TurnLaneType::Mask tag,

View File

@ -9,7 +9,6 @@
#include "guidance/turn_analysis.hpp" #include "guidance/turn_analysis.hpp"
#include "guidance/turn_lane_data.hpp" #include "guidance/turn_lane_data.hpp"
#include "util/attributes.hpp"
#include "util/guidance/turn_lanes.hpp" #include "util/guidance/turn_lanes.hpp"
#include "util/node_based_graph.hpp" #include "util/node_based_graph.hpp"
#include "util/typedefs.hpp" #include "util/typedefs.hpp"
@ -68,8 +67,8 @@ class TurnLaneHandler
~TurnLaneHandler(); ~TurnLaneHandler();
OSRM_ATTR_WARN_UNUSED [[nodiscard]] Intersection
Intersection assignTurnLanes(const NodeID at, const EdgeID via_edge, Intersection intersection); assignTurnLanes(const NodeID at, const EdgeID via_edge, Intersection intersection);
private: private:
mutable std::atomic<std::size_t> count_handled; mutable std::atomic<std::size_t> count_handled;
@ -108,21 +107,20 @@ class TurnLaneHandler
const Intersection &intersection) const; const Intersection &intersection) const;
// in case of a simple intersection, assign the lane entries // in case of a simple intersection, assign the lane entries
OSRM_ATTR_WARN_UNUSED [[nodiscard]] Intersection simpleMatchTuplesToTurns(Intersection intersection,
Intersection simpleMatchTuplesToTurns(Intersection intersection,
const LaneDataVector &lane_data, const LaneDataVector &lane_data,
const LaneDescriptionID lane_string_id); const LaneDescriptionID lane_string_id);
// partition lane data into lane data relevant at current turn and at next turn // partition lane data into lane data relevant at current turn and at next turn
OSRM_ATTR_WARN_UNUSED [[nodiscard]] std::pair<TurnLaneHandler::LaneDataVector, TurnLaneHandler::LaneDataVector>
std::pair<TurnLaneHandler::LaneDataVector, TurnLaneHandler::LaneDataVector> partitionLaneData( partitionLaneData(const NodeID at,
const NodeID at, LaneDataVector turn_lane_data, const Intersection &intersection) const; LaneDataVector turn_lane_data,
const Intersection &intersection) const;
// Sliproad turns have a separated lane to the right/left of other depicted lanes. These lanes // Sliproad turns have a separated lane to the right/left of other depicted lanes. These lanes
// are not necessarily separated clearly from the rest of the way. As a result, we combine both // are not necessarily separated clearly from the rest of the way. As a result, we combine both
// lane entries for our output, while performing the matching with the separated lanes only. // lane entries for our output, while performing the matching with the separated lanes only.
OSRM_ATTR_WARN_UNUSED [[nodiscard]] Intersection handleSliproadTurn(Intersection intersection,
Intersection handleSliproadTurn(Intersection intersection,
const LaneDescriptionID lane_description_id, const LaneDescriptionID lane_description_id,
LaneDataVector lane_data, LaneDataVector lane_data,
const Intersection &previous_intersection); const Intersection &previous_intersection);

View File

@ -5,7 +5,6 @@
#include "guidance/turn_instruction.hpp" #include "guidance/turn_instruction.hpp"
#include "guidance/turn_lane_data.hpp" #include "guidance/turn_lane_data.hpp"
#include "util/attributes.hpp"
#include "util/guidance/turn_lanes.hpp" #include "util/guidance/turn_lanes.hpp"
#include "util/node_based_graph.hpp" #include "util/node_based_graph.hpp"
@ -34,8 +33,8 @@ findBestMatchForReverse(const extractor::TurnLaneType::Mask leftmost_tag,
bool canMatchTrivially(const Intersection &intersection, const LaneDataVector &lane_data); bool canMatchTrivially(const Intersection &intersection, const LaneDataVector &lane_data);
// perform a trivial match on the turn lanes // perform a trivial match on the turn lanes
OSRM_ATTR_WARN_UNUSED [[nodiscard]] Intersection
Intersection triviallyMatchLanesToTurns(Intersection intersection, triviallyMatchLanesToTurns(Intersection intersection,
const LaneDataVector &lane_data, const LaneDataVector &lane_data,
const util::NodeBasedDynamicGraph &node_based_graph, const util::NodeBasedDynamicGraph &node_based_graph,
const LaneDescriptionID lane_string_id, const LaneDescriptionID lane_string_id,

View File

@ -24,7 +24,6 @@
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <algorithm> #include <algorithm>
#include <iostream>
#include <iterator> #include <iterator>
#include <sstream> #include <sstream>
#include <stdexcept> #include <stdexcept>

View File

@ -18,6 +18,7 @@
#include <cerrno> #include <cerrno>
#include <cstring> #include <cstring>
#include <iostream>
#include <tuple> #include <tuple>
#include <type_traits> #include <type_traits>

View File

@ -39,7 +39,7 @@ template <typename Key, typename Value> struct CSVFilesParser
{ {
} }
// Operator returns a lambda function that maps input Key to boost::optional<Value>. // Operator returns a lambda function that maps input Key to std::optional<Value>.
auto operator()(const std::vector<std::string> &csv_filenames) const auto operator()(const std::vector<std::string> &csv_filenames) const
{ {
try try

View File

@ -3,8 +3,7 @@
#include "util/typedefs.hpp" #include "util/typedefs.hpp"
#include <boost/optional.hpp> #include <optional>
#include <vector> #include <vector>
namespace osrm::updater namespace osrm::updater
@ -12,9 +11,9 @@ namespace osrm::updater
template <typename Key, typename Value> struct LookupTable template <typename Key, typename Value> struct LookupTable
{ {
boost::optional<Value> operator()(const Key &key) const std::optional<Value> operator()(const Key &key) const
{ {
using Result = boost::optional<Value>; using Result = std::optional<Value>;
const auto it = const auto it =
std::lower_bound(lookup.begin(), std::lower_bound(lookup.begin(),
lookup.end(), lookup.end(),
@ -50,7 +49,7 @@ struct SpeedSource final
{ {
SpeedSource() : speed(0.), rate() {} SpeedSource() : speed(0.), rate() {}
double speed; double speed;
boost::optional<double> rate; std::optional<double> rate;
std::uint8_t source; std::uint8_t source;
}; };

View File

@ -28,9 +28,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef OSRM_UTIL_ALIAS_HPP #ifndef OSRM_UTIL_ALIAS_HPP
#define OSRM_UTIL_ALIAS_HPP #define OSRM_UTIL_ALIAS_HPP
#include <boost/numeric/conversion/cast.hpp> #include <cstddef>
#include <functional> #include <functional>
#include <iostream> #include <ostream>
#include <type_traits> #include <type_traits>
namespace osrm namespace osrm

View File

@ -1,13 +0,0 @@
#ifndef OSRM_ATTRIBUTES_HPP_
#define OSRM_ATTRIBUTES_HPP_
// OSRM_ATTR_WARN_UNUSED - caller has to use function's return value
// https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html
#if defined(__GNUC__) && (__GNUC__ >= 4)
#define OSRM_ATTR_WARN_UNUSED __attribute__((warn_unused_result))
#else
#define OSRM_ATTR_WARN_UNUSED
#endif
#endif

View File

@ -4,11 +4,11 @@
#include "util/coordinate.hpp" #include "util/coordinate.hpp"
#include <boost/math/constants/constants.hpp> #include <boost/math/constants/constants.hpp>
#include <boost/optional.hpp>
#include <algorithm> #include <algorithm>
#include <cmath> #include <cmath>
#include <numeric> #include <numeric>
#include <optional>
#include <utility> #include <utility>
#include <vector> #include <vector>
@ -109,7 +109,7 @@ double bearing(const Coordinate first_coordinate, const Coordinate second_coordi
double computeAngle(const Coordinate first, const Coordinate second, const Coordinate third); double computeAngle(const Coordinate first, const Coordinate second, const Coordinate third);
// find the center of a circle through three coordinates // find the center of a circle through three coordinates
boost::optional<Coordinate> circleCenter(const Coordinate first_coordinate, std::optional<Coordinate> circleCenter(const Coordinate first_coordinate,
const Coordinate second_coordinate, const Coordinate second_coordinate,
const Coordinate third_coordinate); const Coordinate third_coordinate);

View File

@ -12,7 +12,7 @@
#include "util/typedefs.hpp" #include "util/typedefs.hpp"
#include <iomanip> #include <iomanip>
#include <iostream> #include <ostream>
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <vector> #include <vector>

View File

@ -30,7 +30,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <array> #include <array>
#include <exception> #include <exception>
#include <iostream>
#include <string> #include <string>
#include <utility> #include <utility>

View File

@ -1,6 +1,8 @@
#ifndef SOURCE_MACROS_HPP #ifndef EXCEPTION_UTILS_HPP
#define SOURCE_MACROS_HPP #define EXCEPTION_UTILS_HPP
#include <cstring> #include <cstring>
#include <string>
// Helper macros, don't use these ones // Helper macros, don't use these ones
// STRIP the OSRM_PROJECT_DIR from the front of a filename. Expected to come // STRIP the OSRM_PROJECT_DIR from the front of a filename. Expected to come
@ -12,4 +14,4 @@
// This is the macro to use // This is the macro to use
#define SOURCE_REF (OSRM_SOURCE_FILE_ + ":" + std::to_string(__LINE__)) #define SOURCE_REF (OSRM_SOURCE_FILE_ + ":" + std::to_string(__LINE__))
#endif // SOURCE_MACROS_HPP #endif // EXCEPTION_UTILS_HPP

View File

@ -1,6 +1,7 @@
#ifndef OSRM_GEOJSON_DEBUG_POLICIES #ifndef OSRM_GEOJSON_DEBUG_POLICIES
#define OSRM_GEOJSON_DEBUG_POLICIES #define OSRM_GEOJSON_DEBUG_POLICIES
#include <optional>
#include <vector> #include <vector>
#include "extractor/query_node.hpp" #include "extractor/query_node.hpp"
@ -9,8 +10,6 @@
#include "util/node_based_graph.hpp" #include "util/node_based_graph.hpp"
#include "util/typedefs.hpp" #include "util/typedefs.hpp"
#include <boost/optional.hpp>
namespace osrm::util namespace osrm::util
{ {
@ -20,7 +19,7 @@ struct NodeIdVectorToLineString
// converts a vector of node ids into a linestring geojson feature // converts a vector of node ids into a linestring geojson feature
util::json::Object operator()(const std::vector<NodeID> &node_ids, util::json::Object operator()(const std::vector<NodeID> &node_ids,
const boost::optional<json::Object> &properties = {}) const; const std::optional<json::Object> &properties = {}) const;
const std::vector<util::Coordinate> &node_coordinates; const std::vector<util::Coordinate> &node_coordinates;
}; };
@ -29,7 +28,7 @@ struct CoordinateVectorToLineString
{ {
// converts a vector of node ids into a linestring geojson feature // converts a vector of node ids into a linestring geojson feature
util::json::Object operator()(const std::vector<util::Coordinate> &coordinates, util::json::Object operator()(const std::vector<util::Coordinate> &coordinates,
const boost::optional<json::Object> &properties = {}) const; const std::optional<json::Object> &properties = {}) const;
}; };
struct NodeIdVectorToMultiPoint struct NodeIdVectorToMultiPoint
@ -38,7 +37,7 @@ struct NodeIdVectorToMultiPoint
// converts a vector of node ids into a linestring geojson feature // converts a vector of node ids into a linestring geojson feature
util::json::Object operator()(const std::vector<NodeID> &node_ids, util::json::Object operator()(const std::vector<NodeID> &node_ids,
const boost::optional<json::Object> &properties = {}) const; const std::optional<json::Object> &properties = {}) const;
const std::vector<util::Coordinate> &node_coordinates; const std::vector<util::Coordinate> &node_coordinates;
}; };
@ -47,7 +46,7 @@ struct CoordinateVectorToMultiPoint
{ {
// converts a vector of node ids into a linestring geojson feature // converts a vector of node ids into a linestring geojson feature
util::json::Object operator()(const std::vector<util::Coordinate> &coordinates, util::json::Object operator()(const std::vector<util::Coordinate> &coordinates,
const boost::optional<json::Object> &properties = {}) const; const std::optional<json::Object> &properties = {}) const;
}; };
} // namespace osrm::util } // namespace osrm::util

View File

@ -7,8 +7,7 @@
#include <algorithm> #include <algorithm>
#include <iterator> #include <iterator>
#include <optional>
#include <boost/optional.hpp>
namespace osrm::util namespace osrm::util
{ {
@ -84,7 +83,7 @@ struct NodeIdToCoordinate
inline util::json::Object makeFeature(std::string type, inline util::json::Object makeFeature(std::string type,
util::json::Array coordinates, util::json::Array coordinates,
const boost::optional<util::json::Object> &properties = {}) const std::optional<util::json::Object> &properties = {})
{ {
util::json::Object result; util::json::Object result;
result.values["type"] = "Feature"; result.values["type"] = "Feature";

View File

@ -1,15 +1,14 @@
#ifndef OSRM_UTIL_GUIDANCE_BEARING_CLASS_HPP_ #ifndef OSRM_UTIL_GUIDANCE_BEARING_CLASS_HPP_
#define OSRM_UTIL_GUIDANCE_BEARING_CLASS_HPP_ #define OSRM_UTIL_GUIDANCE_BEARING_CLASS_HPP_
#include "util/std_hash.hpp"
#include "util/typedefs.hpp"
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#include <functional> #include <functional>
#include <vector> #include <vector>
#include <boost/functional/hash.hpp>
#include "util/typedefs.hpp"
namespace osrm::util::guidance namespace osrm::util::guidance
{ {
class BearingClass; class BearingClass;
@ -62,7 +61,10 @@ namespace std
inline size_t hash<::osrm::util::guidance::BearingClass>::operator()( inline size_t hash<::osrm::util::guidance::BearingClass>::operator()(
const ::osrm::util::guidance::BearingClass &bearing_class) const const ::osrm::util::guidance::BearingClass &bearing_class) const
{ {
return boost::hash_value(bearing_class.available_bearings); std::size_t value = 0;
hash_range(
value, bearing_class.available_bearings.cbegin(), bearing_class.available_bearings.cend());
return value;
} }
} // namespace std } // namespace std

View File

@ -6,18 +6,16 @@
#include "extractor/name_table.hpp" #include "extractor/name_table.hpp"
#include "extractor/suffix_table.hpp" #include "extractor/suffix_table.hpp"
#include "util/attributes.hpp"
#include "util/typedefs.hpp" #include "util/typedefs.hpp"
#include <boost/algorithm/string.hpp>
#include <algorithm> #include <algorithm>
#include <string> #include <string>
#include <tuple> #include <tuple>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/predicate.hpp>
namespace osrm::util::guidance namespace osrm::util::guidance
{ {
// Name Change Logic // Name Change Logic

View File

@ -1,36 +1,22 @@
#ifndef OSRM_UTIL_GUIDANCE_TURN_LANES_HPP #ifndef OSRM_UTIL_GUIDANCE_TURN_LANES_HPP
#define OSRM_UTIL_GUIDANCE_TURN_LANES_HPP #define OSRM_UTIL_GUIDANCE_TURN_LANES_HPP
#include "util/concurrent_id_map.hpp"
#include "util/std_hash.hpp"
#include "util/typedefs.hpp"
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#include <functional> #include <functional>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
#include "util/concurrent_id_map.hpp"
#include "util/typedefs.hpp"
#include <boost/functional/hash.hpp>
namespace osrm::util::guidance namespace osrm::util::guidance
{ {
class LaneTuple; class LaneTuple;
class LaneTupleIdPair; class LaneTupleIdPair;
} // namespace osrm::util::guidance } // namespace osrm::util::guidance
namespace std
{
template <> struct hash<::osrm::util::guidance::LaneTuple>
{
inline std::size_t operator()(const ::osrm::util::guidance::LaneTuple &bearing_class) const;
};
template <> struct hash<::osrm::util::guidance::LaneTupleIdPair>
{
inline std::size_t
operator()(const ::osrm::util::guidance::LaneTupleIdPair &bearing_class) const;
};
} // namespace std
namespace osrm::util::guidance namespace osrm::util::guidance
{ {
@ -61,14 +47,6 @@ class LaneTuple
LaneID lanes_in_turn; LaneID lanes_in_turn;
LaneID first_lane_from_the_right; // is INVALID_LANEID when no lanes present LaneID first_lane_from_the_right; // is INVALID_LANEID when no lanes present
friend std::size_t hash_value(const LaneTuple &tup)
{
std::size_t seed{0};
boost::hash_combine(seed, tup.lanes_in_turn);
boost::hash_combine(seed, tup.first_lane_from_the_right);
return seed;
}
}; };
class LaneTupleIdPair class LaneTupleIdPair
@ -78,18 +56,36 @@ class LaneTupleIdPair
LaneDescriptionID second; LaneDescriptionID second;
bool operator==(const LaneTupleIdPair &other) const; bool operator==(const LaneTupleIdPair &other) const;
};
friend std::size_t hash_value(const LaneTupleIdPair &pair) using LaneDataIdMap = ConcurrentIDMap<LaneTupleIdPair, LaneDataID>;
} // namespace osrm::util::guidance
namespace std
{
template <> struct hash<::osrm::util::guidance::LaneTuple>
{
inline std::size_t operator()(const ::osrm::util::guidance::LaneTuple &lane_tuple) const
{ {
std::size_t seed{0}; std::size_t seed{0};
boost::hash_combine(seed, pair.first); hash_combine(seed, lane_tuple.lanes_in_turn);
boost::hash_combine(seed, pair.second); hash_combine(seed, lane_tuple.first_lane_from_the_right);
return seed; return seed;
} }
}; };
using LaneDataIdMap = ConcurrentIDMap<LaneTupleIdPair, LaneDataID, boost::hash<LaneTupleIdPair>>; template <> struct hash<::osrm::util::guidance::LaneTupleIdPair>
{
} // namespace osrm::util::guidance inline std::size_t
operator()(const ::osrm::util::guidance::LaneTupleIdPair &lane_tuple_id_pair) const
{
std::size_t seed{0};
hash_combine(seed, lane_tuple_id_pair.first);
hash_combine(seed, lane_tuple_id_pair.second);
return seed;
}
};
} // namespace std
#endif /* OSRM_UTIL_GUIDANCE_TURN_LANES_HPP */ #endif /* OSRM_UTIL_GUIDANCE_TURN_LANES_HPP */

View File

@ -10,7 +10,6 @@ extern "C"
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <iostream>
#include <string> #include <string>
namespace osrm::util namespace osrm::util

View File

@ -9,7 +9,6 @@
#include <tbb/parallel_sort.h> #include <tbb/parallel_sort.h>
#include <iostream>
#include <memory> #include <memory>
#include <utility> #include <utility>

View File

@ -3,12 +3,12 @@
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/heap/d_ary_heap.hpp> #include <boost/heap/d_ary_heap.hpp>
#include <boost/optional.hpp>
#include <algorithm> #include <algorithm>
#include <cstdint> #include <cstdint>
#include <limits> #include <limits>
#include <map> #include <map>
#include <optional>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
@ -290,26 +290,26 @@ class QueryHeap
return inserted_nodes[index].node == node; return inserted_nodes[index].node == node;
} }
boost::optional<HeapNode &> GetHeapNodeIfWasInserted(const NodeID node) HeapNode *GetHeapNodeIfWasInserted(const NodeID node)
{ {
const auto index = node_index.peek_index(node); const auto index = node_index.peek_index(node);
if (index >= static_cast<decltype(index)>(inserted_nodes.size()) || if (index >= static_cast<decltype(index)>(inserted_nodes.size()) ||
inserted_nodes[index].node != node) inserted_nodes[index].node != node)
{ {
return {}; return nullptr;
} }
return inserted_nodes[index]; return &inserted_nodes[index];
} }
boost::optional<const HeapNode &> GetHeapNodeIfWasInserted(const NodeID node) const const HeapNode *GetHeapNodeIfWasInserted(const NodeID node) const
{ {
const auto index = node_index.peek_index(node); const auto index = node_index.peek_index(node);
if (index >= static_cast<decltype(index)>(inserted_nodes.size()) || if (index >= static_cast<decltype(index)>(inserted_nodes.size()) ||
inserted_nodes[index].node != node) inserted_nodes[index].node != node)
{ {
return {}; return nullptr;
} }
return inserted_nodes[index]; return &inserted_nodes[index];
} }
NodeID Min() const NodeID Min() const

View File

@ -1,6 +1,7 @@
#ifndef OSRM_STATIC_ASSERT_HPP #ifndef OSRM_STATIC_ASSERT_HPP
#define OSRM_STATIC_ASSERT_HPP #define OSRM_STATIC_ASSERT_HPP
#include <iterator>
#include <type_traits> #include <type_traits>
namespace osrm::util namespace osrm::util
@ -8,14 +9,13 @@ namespace osrm::util
template <typename It, typename Value> inline void static_assert_iter_value() template <typename It, typename Value> inline void static_assert_iter_value()
{ {
using IterValueType = typename std::iterator_traits<It>::value_type; static_assert(std::is_same_v<std::iter_value_t<It>, Value>, "");
static_assert(std::is_same<IterValueType, Value>::value, "");
} }
template <typename It, typename Category> inline void static_assert_iter_category() template <typename It, typename Category> inline void static_assert_iter_category()
{ {
using IterCategoryType = typename std::iterator_traits<It>::iterator_category; using IterCategoryType = typename std::iterator_traits<It>::iterator_category;
static_assert(std::is_base_of<Category, IterCategoryType>::value, ""); static_assert(std::is_base_of_v<Category, IterCategoryType>, "");
} }
} // namespace osrm::util } // namespace osrm::util

View File

@ -1,7 +1,11 @@
#ifndef STD_HASH_HPP #ifndef STD_HASH_HPP
#define STD_HASH_HPP #define STD_HASH_HPP
#include <cstddef>
#include <functional> #include <functional>
#include <tuple>
#include <utility>
#include <vector>
// this is largely inspired by boost's hash combine as can be found in // this is largely inspired by boost's hash combine as can be found in
// "The C++ Standard Library" 2nd Edition. Nicolai M. Josuttis. 2012. // "The C++ Standard Library" 2nd Edition. Nicolai M. Josuttis. 2012.
@ -11,6 +15,14 @@ template <typename T> void hash_combine(std::size_t &seed, const T &val)
seed ^= std::hash<T>()(val) + 0x9e3779b9 + (seed << 6) + (seed >> 2); seed ^= std::hash<T>()(val) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
} }
template <typename It> void hash_range(std::size_t &seed, It first, const It last)
{
for (; first != last; ++first)
{
hash_combine(seed, *first);
}
}
template <typename T> void hash_val(std::size_t &seed, const T &val) { hash_combine(seed, val); } template <typename T> void hash_val(std::size_t &seed, const T &val) { hash_combine(seed, val); }
template <typename T, typename... Types> template <typename T, typename... Types>
@ -29,13 +41,39 @@ template <typename... Types> std::size_t hash_val(const Types &...args)
namespace std namespace std
{ {
template <typename... T> struct hash<std::tuple<T...>>
{
template <std::size_t... I>
static auto apply_tuple(const std::tuple<T...> &t, std::index_sequence<I...>)
{
std::size_t seed = 0;
return ((seed = hash_val(std::get<I>(t), seed)), ...);
}
auto operator()(const std::tuple<T...> &t) const
{
return apply_tuple(t, std::make_index_sequence<sizeof...(T)>());
}
};
template <typename T1, typename T2> struct hash<std::pair<T1, T2>> template <typename T1, typename T2> struct hash<std::pair<T1, T2>>
{ {
size_t operator()(const std::pair<T1, T2> &pair) const std::size_t operator()(const std::pair<T1, T2> &pair) const
{ {
return hash_val(pair.first, pair.second); return hash_val(pair.first, pair.second);
} }
}; };
template <typename T> struct hash<std::vector<T>>
{
auto operator()(const std::vector<T> &lane_description) const
{
std::size_t seed = 0;
hash_range(seed, lane_description.begin(), lane_description.end());
return seed;
}
};
} // namespace std } // namespace std
#endif // STD_HASH_HPP #endif // STD_HASH_HPP

View File

@ -6,11 +6,11 @@
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
#include <boost/geometry.hpp> #include <boost/geometry.hpp>
#include <boost/geometry/index/rtree.hpp> #include <boost/geometry/index/rtree.hpp>
#include <boost/optional.hpp>
#include <rapidjson/document.h> #include <rapidjson/document.h>
#include <chrono> #include <chrono>
#include <optional>
namespace osrm::updater namespace osrm::updater
{ {
@ -34,7 +34,7 @@ class Timezoner
Timezoner(const char geojson[], std::time_t utc_time_now); Timezoner(const char geojson[], std::time_t utc_time_now);
Timezoner(const boost::filesystem::path &tz_shapes_filename, std::time_t utc_time_now); Timezoner(const boost::filesystem::path &tz_shapes_filename, std::time_t utc_time_now);
boost::optional<struct tm> operator()(const point_t &point) const; std::optional<struct tm> operator()(const point_t &point) const;
private: private:
void LoadLocalTimesRTree(rapidjson::Document &geojson, std::time_t utc_time); void LoadLocalTimesRTree(rapidjson::Document &geojson, std::time_t utc_time);

View File

@ -364,7 +364,6 @@ const constexpr double SCALING_FACTOR = 4. / boost::math::constants::pi<double>(
inline double atan2_lookup(double y, double x) inline double atan2_lookup(double y, double x)
{ {
using namespace boost::math::constants; using namespace boost::math::constants;
if (std::abs(x) < std::numeric_limits<double>::epsilon()) if (std::abs(x) < std::numeric_limits<double>::epsilon())

View File

@ -13,6 +13,8 @@ function run_benchmarks_for_folder {
./$BENCHMARKS_FOLDER/match-bench "./$FOLDER/test/data/mld/monaco.osrm" mld > "$RESULTS_FOLDER/match_mld.bench" ./$BENCHMARKS_FOLDER/match-bench "./$FOLDER/test/data/mld/monaco.osrm" mld > "$RESULTS_FOLDER/match_mld.bench"
./$BENCHMARKS_FOLDER/match-bench "./$FOLDER/test/data/ch/monaco.osrm" ch > "$RESULTS_FOLDER/match_ch.bench" ./$BENCHMARKS_FOLDER/match-bench "./$FOLDER/test/data/ch/monaco.osrm" ch > "$RESULTS_FOLDER/match_ch.bench"
./$BENCHMARKS_FOLDER/route-bench "./$FOLDER/test/data/mld/monaco.osrm" mld > "$RESULTS_FOLDER/route_mld.bench" || true # TODO: remove `true` when this benchmark will be merged to master
./$BENCHMARKS_FOLDER/route-bench "./$FOLDER/test/data/ch/monaco.osrm" ch > "$RESULTS_FOLDER/route_ch.bench" || true # TODO: remove `true` when this benchmark will be merged to master
./$BENCHMARKS_FOLDER/alias-bench > "$RESULTS_FOLDER/alias.bench" ./$BENCHMARKS_FOLDER/alias-bench > "$RESULTS_FOLDER/alias.bench"
./$BENCHMARKS_FOLDER/json-render-bench "./$FOLDER/src/benchmarks/portugal_to_korea.json" > "$RESULTS_FOLDER/json-render.bench" ./$BENCHMARKS_FOLDER/json-render-bench "./$FOLDER/src/benchmarks/portugal_to_korea.json" > "$RESULTS_FOLDER/json-render.bench"
./$BENCHMARKS_FOLDER/packedvector-bench > "$RESULTS_FOLDER/packedvector.bench" ./$BENCHMARKS_FOLDER/packedvector-bench > "$RESULTS_FOLDER/packedvector.bench"

View File

@ -13,7 +13,7 @@ OSMIUM_PATH="osmcode/libosmium"
OSMIUM_TAG=v2.14.0 OSMIUM_TAG=v2.14.0
VARIANT_PATH="mapbox/variant" VARIANT_PATH="mapbox/variant"
VARIANT_TAG=v1.1.3 VARIANT_TAG=v1.2.0
SOL_PATH="ThePhD/sol2" SOL_PATH="ThePhD/sol2"
SOL_TAG=v2.17.5 SOL_TAG=v2.17.5
@ -34,7 +34,7 @@ FMT_PATH="fmtlib/fmt"
FMT_TAG=v10.2.1 FMT_TAG=v10.2.1
function update_subtree () { function update_subtree () {
name=${1^^} name=$(echo "$1" | tr '[:lower:]' '[:upper:]')
path=$(tmpvar=${name}_PATH && echo ${!tmpvar}) path=$(tmpvar=${name}_PATH && echo ${!tmpvar})
tag=$(tmpvar=${name}_TAG && echo ${!tmpvar}) tag=$(tmpvar=${name}_TAG && echo ${!tmpvar})
dir=$(basename $path) dir=$(basename $path)

View File

@ -30,6 +30,18 @@ target_link_libraries(match-bench
${TBB_LIBRARIES} ${TBB_LIBRARIES}
${MAYBE_SHAPEFILE}) ${MAYBE_SHAPEFILE})
add_executable(route-bench
EXCLUDE_FROM_ALL
route.cpp
$<TARGET_OBJECTS:UTIL>)
target_link_libraries(route-bench
osrm
${BOOST_BASE_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
${TBB_LIBRARIES}
${MAYBE_SHAPEFILE})
add_executable(json-render-bench add_executable(json-render-bench
EXCLUDE_FROM_ALL EXCLUDE_FROM_ALL
json_render.cpp json_render.cpp
@ -72,5 +84,6 @@ add_custom_target(benchmarks
rtree-bench rtree-bench
packedvector-bench packedvector-bench
match-bench match-bench
route-bench
json-render-bench json-render-bench
alias-bench) alias-bench)

View File

@ -5,6 +5,7 @@
#include <algorithm> #include <algorithm>
#include <iomanip> #include <iomanip>
#include <iostream>
#include <numeric> #include <numeric>
#include <random> #include <random>
#include <string> #include <string>

View File

@ -5,6 +5,7 @@
#include <algorithm> #include <algorithm>
#include <iomanip> #include <iomanip>
#include <iostream>
#include <numeric> #include <numeric>
#include <random> #include <random>
#include <string> #include <string>

166
src/benchmarks/route.cpp Normal file
View File

@ -0,0 +1,166 @@
#include "engine/engine_config.hpp"
#include "util/coordinate.hpp"
#include "util/timing_util.hpp"
#include "osrm/route_parameters.hpp"
#include "osrm/coordinate.hpp"
#include "osrm/engine_config.hpp"
#include "osrm/json_container.hpp"
#include "osrm/osrm.hpp"
#include "osrm/status.hpp"
#include <boost/assert.hpp>
#include <boost/optional/optional.hpp>
#include <cstdlib>
#include <exception>
#include <iostream>
#include <optional>
#include <stdexcept>
#include <string>
#include <vector>
int main(int argc, const char *argv[])
try
{
if (argc < 2)
{
std::cerr << "Usage: " << argv[0] << " data.osrm\n";
return EXIT_FAILURE;
}
using namespace osrm;
// Configure based on a .osrm base path, and no datasets in shared mem from osrm-datastore
EngineConfig config;
config.storage_config = {argv[1]};
config.algorithm = (argc > 2 && std::string{argv[2]} == "mld") ? EngineConfig::Algorithm::MLD
: EngineConfig::Algorithm::CH;
config.use_shared_memory = false;
// Routing machine with several services (such as Route, Table, Nearest, Trip, Match)
OSRM osrm{config};
struct Benchmark
{
std::string name;
std::vector<util::Coordinate> coordinates;
RouteParameters::OverviewType overview;
bool steps = false;
std::optional<size_t> alternatives = std::nullopt;
std::optional<double> radius = std::nullopt;
};
auto run_benchmark = [&](const Benchmark &benchmark)
{
RouteParameters params;
params.overview = benchmark.overview;
params.steps = benchmark.steps;
params.coordinates = benchmark.coordinates;
if (benchmark.alternatives)
{
params.alternatives = *benchmark.alternatives;
}
if (benchmark.radius)
{
params.radiuses = std::vector<boost::optional<double>>(
params.coordinates.size(), boost::make_optional(*benchmark.radius));
}
TIMER_START(routes);
auto NUM = 1000;
for (int i = 0; i < NUM; ++i)
{
engine::api::ResultT result = json::Object();
const auto rc = osrm.Route(params, result);
auto &json_result = result.get<json::Object>();
if (rc != Status::Ok || json_result.values.find("routes") == json_result.values.end())
{
throw std::runtime_error{"Couldn't route"};
}
}
TIMER_STOP(routes);
std::cout << benchmark.name << std::endl;
std::cout << TIMER_MSEC(routes) << "ms" << std::endl;
std::cout << TIMER_MSEC(routes) / NUM << "ms/req" << std::endl;
};
std::vector<Benchmark> benchmarks = {
{"1000 routes, 3 coordinates, no alternatives, overview=full, steps=true",
{{FloatLongitude{7.437602352715465}, FloatLatitude{43.75030522209604}},
{FloatLongitude{7.421844922513342}, FloatLatitude{43.73690777888953}},
{FloatLongitude{7.412303912230966}, FloatLatitude{43.72851046529198}}},
RouteParameters::OverviewType::Full,
true,
std::nullopt},
{"1000 routes, 2 coordinates, no alternatives, overview=full, steps=true",
{{FloatLongitude{7.437602352715465}, FloatLatitude{43.75030522209604}},
{FloatLongitude{7.412303912230966}, FloatLatitude{43.72851046529198}}},
RouteParameters::OverviewType::Full,
true,
std::nullopt},
{"1000 routes, 2 coordinates, 3 alternatives, overview=full, steps=true",
{{FloatLongitude{7.437602352715465}, FloatLatitude{43.75030522209604}},
{FloatLongitude{7.412303912230966}, FloatLatitude{43.72851046529198}}},
RouteParameters::OverviewType::Full,
true,
3},
{"1000 routes, 3 coordinates, no alternatives, overview=false, steps=false",
{{FloatLongitude{7.437602352715465}, FloatLatitude{43.75030522209604}},
{FloatLongitude{7.421844922513342}, FloatLatitude{43.73690777888953}},
{FloatLongitude{7.412303912230966}, FloatLatitude{43.72851046529198}}},
RouteParameters::OverviewType::False,
false,
std::nullopt},
{"1000 routes, 2 coordinates, no alternatives, overview=false, steps=false",
{{FloatLongitude{7.437602352715465}, FloatLatitude{43.75030522209604}},
{FloatLongitude{7.412303912230966}, FloatLatitude{43.72851046529198}}},
RouteParameters::OverviewType::False,
false,
std::nullopt},
{"1000 routes, 2 coordinates, 3 alternatives, overview=false, steps=false",
{{FloatLongitude{7.437602352715465}, FloatLatitude{43.75030522209604}},
{FloatLongitude{7.412303912230966}, FloatLatitude{43.72851046529198}}},
RouteParameters::OverviewType::False,
false,
3},
{"1000 routes, 3 coordinates, no alternatives, overview=false, steps=false, radius=750",
{{FloatLongitude{7.437602352715465}, FloatLatitude{43.75030522209604}},
{FloatLongitude{7.421844922513342}, FloatLatitude{43.73690777888953}},
{FloatLongitude{7.412303912230966}, FloatLatitude{43.72851046529198}}},
RouteParameters::OverviewType::False,
false,
std::nullopt,
750},
{"1000 routes, 2 coordinates, no alternatives, overview=false, steps=false, radius=750",
{{FloatLongitude{7.437602352715465}, FloatLatitude{43.75030522209604}},
{FloatLongitude{7.412303912230966}, FloatLatitude{43.72851046529198}}},
RouteParameters::OverviewType::False,
false,
std::nullopt,
750},
{"1000 routes, 2 coordinates, 3 alternatives, overview=false, steps=false, radius=750",
{{FloatLongitude{7.437602352715465}, FloatLatitude{43.75030522209604}},
{FloatLongitude{7.412303912230966}, FloatLatitude{43.72851046529198}}},
RouteParameters::OverviewType::False,
false,
3,
750}
};
for (const auto &benchmark : benchmarks)
{
run_benchmark(benchmark);
}
return EXIT_SUCCESS;
}
catch (const std::exception &e)
{
std::cerr << "Error: " << e.what() << std::endl;
return EXIT_FAILURE;
}

View File

@ -1,7 +1,6 @@
#include "contractor/contractor.hpp" #include "contractor/contractor.hpp"
#include "contractor/contract_excludable_graph.hpp" #include "contractor/contract_excludable_graph.hpp"
#include "contractor/contracted_edge_container.hpp" #include "contractor/contracted_edge_container.hpp"
#include "contractor/crc32_processor.hpp"
#include "contractor/files.hpp" #include "contractor/files.hpp"
#include "contractor/graph_contractor.hpp" #include "contractor/graph_contractor.hpp"
#include "contractor/graph_contractor_adaptors.hpp" #include "contractor/graph_contractor_adaptors.hpp"

View File

@ -433,8 +433,7 @@ void suppressStep(RouteStep &step_at_turn_location, RouteStep &step_after_turn_l
} }
// OTHER IMPLEMENTATIONS // OTHER IMPLEMENTATIONS
OSRM_ATTR_WARN_UNUSED [[nodiscard]] RouteSteps collapseTurnInstructions(RouteSteps steps)
RouteSteps collapseTurnInstructions(RouteSteps steps)
{ {
// make sure we can safely iterate over all steps (has depart/arrive with TurnType::NoTurn) // make sure we can safely iterate over all steps (has depart/arrive with TurnType::NoTurn)
BOOST_ASSERT(!hasTurnType(steps.front()) && !hasTurnType(steps.back())); BOOST_ASSERT(!hasTurnType(steps.front()) && !hasTurnType(steps.back()));
@ -589,8 +588,7 @@ RouteSteps collapseTurnInstructions(RouteSteps steps)
} }
// OTHER IMPLEMENTATIONS // OTHER IMPLEMENTATIONS
OSRM_ATTR_WARN_UNUSED [[nodiscard]] RouteSteps collapseSegregatedTurnInstructions(RouteSteps steps)
RouteSteps collapseSegregatedTurnInstructions(RouteSteps steps)
{ {
// make sure we can safely iterate over all steps (has depart/arrive with TurnType::NoTurn) // make sure we can safely iterate over all steps (has depart/arrive with TurnType::NoTurn)
BOOST_ASSERT(!hasTurnType(steps.front()) && !hasTurnType(steps.back())); BOOST_ASSERT(!hasTurnType(steps.front()) && !hasTurnType(steps.back()));

View File

@ -9,8 +9,6 @@
#include <limits> #include <limits>
#include <string> #include <string>
#include <iostream>
namespace osrm::extractor namespace osrm::extractor
{ {

View File

@ -19,7 +19,6 @@
#include "util/timing_util.hpp" #include "util/timing_util.hpp"
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/functional/hash.hpp>
#include <boost/numeric/conversion/cast.hpp> #include <boost/numeric/conversion/cast.hpp>
#include <algorithm> #include <algorithm>

View File

@ -13,6 +13,7 @@
#include "util/for_each_indexed.hpp" #include "util/for_each_indexed.hpp"
#include "util/for_each_pair.hpp" #include "util/for_each_pair.hpp"
#include "util/log.hpp" #include "util/log.hpp"
#include "util/std_hash.hpp"
#include "util/timing_util.hpp" #include "util/timing_util.hpp"
#include <boost/assert.hpp> #include <boost/assert.hpp>
@ -955,8 +956,7 @@ void ExtractionContainers::PrepareTrafficSignals(
TIMER_START(prepare_traffic_signals); TIMER_START(prepare_traffic_signals);
std::unordered_set<NodeID> bidirectional; std::unordered_set<NodeID> bidirectional;
std::unordered_set<std::pair<NodeID, NodeID>, boost::hash<std::pair<NodeID, NodeID>>> std::unordered_set<std::pair<NodeID, NodeID>> unidirectional;
unidirectional;
for (const auto &osm_node : bidirectional_signal_nodes) for (const auto &osm_node : bidirectional_signal_nodes)
{ {

View File

@ -50,7 +50,6 @@
#include <atomic> #include <atomic>
#include <bitset> #include <bitset>
#include <chrono> #include <chrono>
#include <iostream>
#include <memory> #include <memory>
#include <thread> #include <thread>
#include <tuple> #include <tuple>

View File

@ -66,7 +66,7 @@ SelectRoadByNameOnlyChoiceAndStraightness::SelectRoadByNameOnlyChoiceAndStraight
{ {
} }
boost::optional<EdgeID> SelectRoadByNameOnlyChoiceAndStraightness::operator()( std::optional<EdgeID> SelectRoadByNameOnlyChoiceAndStraightness::operator()(
const NodeID /*nid*/, const NodeID /*nid*/,
const EdgeID /*via_edge_id*/, const EdgeID /*via_edge_id*/,
const IntersectionView &intersection, const IntersectionView &intersection,
@ -118,7 +118,7 @@ SelectStraightmostRoadByNameAndOnlyChoice::SelectStraightmostRoadByNameAndOnlyCh
{ {
} }
boost::optional<EdgeID> SelectStraightmostRoadByNameAndOnlyChoice::operator()( std::optional<EdgeID> SelectStraightmostRoadByNameAndOnlyChoice::operator()(
const NodeID /*nid*/, const NodeID /*nid*/,
const EdgeID /*via_edge_id*/, const EdgeID /*via_edge_id*/,
const IntersectionView &intersection, const IntersectionView &intersection,
@ -241,7 +241,7 @@ boost::optional<EdgeID> SelectStraightmostRoadByNameAndOnlyChoice::operator()(
return {}; return {};
} }
return is_only_choice_with_same_name ? boost::optional<EdgeID>(min_element->eid) : boost::none; return is_only_choice_with_same_name ? std::optional<EdgeID>(min_element->eid) : std::nullopt;
} }
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------

View File

@ -1,9 +1,9 @@
#include "extractor/maneuver_override_relation_parser.hpp" #include "extractor/maneuver_override_relation_parser.hpp"
#include "extractor/maneuver_override.hpp" #include "extractor/maneuver_override.hpp"
#include <boost/optional/optional.hpp>
#include <boost/ref.hpp> #include <boost/ref.hpp>
#include <optional>
#include <osmium/osm.hpp> #include <osmium/osm.hpp>
#include <osmium/tags/filter.hpp> #include <osmium/tags/filter.hpp>
#include <osmium/tags/taglist.hpp> #include <osmium/tags/taglist.hpp>
@ -21,7 +21,7 @@ ManeuverOverrideRelationParser::ManeuverOverrideRelationParser() {}
* into an InputManeuverOverride object, if the relation is considered * into an InputManeuverOverride object, if the relation is considered
* valid (i.e. has the minimum tags we expect). * valid (i.e. has the minimum tags we expect).
*/ */
boost::optional<InputManeuverOverride> std::optional<InputManeuverOverride>
ManeuverOverrideRelationParser::TryParse(const osmium::Relation &relation) const ManeuverOverrideRelationParser::TryParse(const osmium::Relation &relation) const
{ {
@ -35,7 +35,7 @@ ManeuverOverrideRelationParser::TryParse(const osmium::Relation &relation) const
if (osmium::tags::match_none_of(tag_list, filter)) if (osmium::tags::match_none_of(tag_list, filter))
// if it's not a maneuver, continue; // if it's not a maneuver, continue;
{ {
return boost::none; return std::nullopt;
} }
// we pretend every restriction is a conditional restriction. If we do not find any restriction, // we pretend every restriction is a conditional restriction. If we do not find any restriction,
@ -130,7 +130,7 @@ ManeuverOverrideRelationParser::TryParse(const osmium::Relation &relation) const
} }
else else
{ {
return boost::none; return std::nullopt;
} }
return maneuver_override; return maneuver_override;
} }

View File

@ -427,7 +427,7 @@ void IntersectionHandler::assignTrivialTurns(const EdgeID via_eid,
} }
} }
boost::optional<IntersectionHandler::IntersectionViewAndNode> std::optional<IntersectionHandler::IntersectionViewAndNode>
IntersectionHandler::getNextIntersection(const NodeID at, const EdgeID via) const IntersectionHandler::getNextIntersection(const NodeID at, const EdgeID via) const
{ {
// We use the intersection generator to jump over traffic signals, barriers. The intersection // We use the intersection generator to jump over traffic signals, barriers. The intersection
@ -450,7 +450,7 @@ IntersectionHandler::getNextIntersection(const NodeID at, const EdgeID via) cons
if (intersection_parameters.node == SPECIAL_NODEID || if (intersection_parameters.node == SPECIAL_NODEID ||
intersection_parameters.edge == SPECIAL_EDGEID) intersection_parameters.edge == SPECIAL_EDGEID)
{ {
return boost::none; return std::nullopt;
} }
auto intersection = extractor::intersection::getConnectedRoads<false>(node_based_graph, auto intersection = extractor::intersection::getConnectedRoads<false>(node_based_graph,
@ -465,11 +465,10 @@ IntersectionHandler::getNextIntersection(const NodeID at, const EdgeID via) cons
if (intersection.size() <= 2 || intersection.isTrafficSignalOrBarrier()) if (intersection.size() <= 2 || intersection.isTrafficSignalOrBarrier())
{ {
return boost::none; return std::nullopt;
} }
return boost::make_optional( return std::make_optional(IntersectionViewAndNode{std::move(intersection), intersection_node});
IntersectionViewAndNode{std::move(intersection), intersection_node});
} }
bool IntersectionHandler::isSameName(const EdgeID source_edge_id, const EdgeID target_edge_id) const bool IntersectionHandler::isSameName(const EdgeID source_edge_id, const EdgeID target_edge_id) const

View File

@ -634,7 +634,7 @@ Intersection SliproadHandler::operator()(const NodeID /*nid*/,
// Implementation details // Implementation details
boost::optional<std::size_t> SliproadHandler::getObviousIndexWithSliproads( std::optional<std::size_t> SliproadHandler::getObviousIndexWithSliproads(
const EdgeID from, const Intersection &intersection, const NodeID at) const const EdgeID from, const Intersection &intersection, const NodeID at) const
{ {
BOOST_ASSERT(from != SPECIAL_EDGEID); BOOST_ASSERT(from != SPECIAL_EDGEID);
@ -645,14 +645,14 @@ boost::optional<std::size_t> SliproadHandler::getObviousIndexWithSliproads(
if (index != 0) if (index != 0)
{ {
return boost::make_optional(index); return std::make_optional(index);
} }
// Otherwise check if the road is forking into two and one of them is a Sliproad; // Otherwise check if the road is forking into two and one of them is a Sliproad;
// then the non-Sliproad is the obvious one. // then the non-Sliproad is the obvious one.
if (intersection.size() != 3) if (intersection.size() != 3)
{ {
return boost::none; return std::nullopt;
} }
const auto forking = intersection[1].instruction.type == TurnType::Fork && const auto forking = intersection[1].instruction.type == TurnType::Fork &&
@ -660,7 +660,7 @@ boost::optional<std::size_t> SliproadHandler::getObviousIndexWithSliproads(
if (!forking) if (!forking)
{ {
return boost::none; return std::nullopt;
} }
const auto first = getNextIntersection(at, intersection.getRightmostRoad().eid); const auto first = getNextIntersection(at, intersection.getRightmostRoad().eid);
@ -668,27 +668,27 @@ boost::optional<std::size_t> SliproadHandler::getObviousIndexWithSliproads(
if (!first || !second) if (!first || !second)
{ {
return boost::none; return std::nullopt;
} }
if (first->intersection.isDeadEnd() || second->intersection.isDeadEnd()) if (first->intersection.isDeadEnd() || second->intersection.isDeadEnd())
{ {
return boost::none; return std::nullopt;
} }
// In case of loops at the end of the road, we will arrive back at the intersection // In case of loops at the end of the road, we will arrive back at the intersection
// itself. If that is the case, the road is obviously not a sliproad. // itself. If that is the case, the road is obviously not a sliproad.
if (canBeTargetOfSliproad(first->intersection) && at != second->node) if (canBeTargetOfSliproad(first->intersection) && at != second->node)
{ {
return boost::make_optional(std::size_t{2}); return std::make_optional(std::size_t{2});
} }
if (canBeTargetOfSliproad(second->intersection) && at != first->node) if (canBeTargetOfSliproad(second->intersection) && at != first->node)
{ {
return boost::make_optional(std::size_t{1}); return std::make_optional(std::size_t{1});
} }
return boost::none; return std::nullopt;
} }
bool SliproadHandler::nextIntersectionIsTooFarAway(const NodeID start, const EdgeID onto) const bool SliproadHandler::nextIntersectionIsTooFarAway(const NodeID start, const EdgeID onto) const

View File

@ -6,10 +6,10 @@
#include <algorithm> #include <algorithm>
#include <limits> #include <limits>
#include <optional>
#include <utility> #include <utility>
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/optional.hpp>
using osrm::util::angularDeviation; using osrm::util::angularDeviation;
@ -590,7 +590,7 @@ Intersection TurnHandler::assignRightTurns(const EdgeID via_edge,
} }
// finds a fork candidate by just looking at the geometry and angle of an intersection // finds a fork candidate by just looking at the geometry and angle of an intersection
boost::optional<TurnHandler::Fork> std::optional<TurnHandler::Fork>
TurnHandler::findForkCandidatesByGeometry(Intersection &intersection) const TurnHandler::findForkCandidatesByGeometry(Intersection &intersection) const
{ {
if (intersection.size() >= 3) if (intersection.size() >= 3)
@ -647,7 +647,7 @@ TurnHandler::findForkCandidatesByGeometry(Intersection &intersection) const
} }
} }
} }
return boost::none; return std::nullopt;
} }
// check if the fork candidates (all roads between left and right) and the // check if the fork candidates (all roads between left and right) and the
@ -695,7 +695,7 @@ bool TurnHandler::isCompatibleByRoadClass(const Intersection &intersection, cons
// Checks whether a three-way-intersection coming from `via_edge` is a fork // Checks whether a three-way-intersection coming from `via_edge` is a fork
// with `intersection` as described as in #IntersectionExplanation@intersection_handler.hpp // with `intersection` as described as in #IntersectionExplanation@intersection_handler.hpp
boost::optional<TurnHandler::Fork> TurnHandler::findFork(const EdgeID via_edge, std::optional<TurnHandler::Fork> TurnHandler::findFork(const EdgeID via_edge,
Intersection &intersection) const Intersection &intersection) const
{ {
auto fork = findForkCandidatesByGeometry(intersection); auto fork = findForkCandidatesByGeometry(intersection);
@ -740,7 +740,7 @@ boost::optional<TurnHandler::Fork> TurnHandler::findFork(const EdgeID via_edge,
} }
} }
return boost::none; return std::nullopt;
} }
void TurnHandler::handleDistinctConflict(const EdgeID via_edge, void TurnHandler::handleDistinctConflict(const EdgeID via_edge,

View File

@ -1,6 +1,5 @@
#include "partitioner/bisection_graph_view.hpp" #include "partitioner/bisection_graph_view.hpp"
#include <iostream>
#include <iterator> #include <iterator>
#include <boost/assert.hpp> #include <boost/assert.hpp>

View File

@ -31,7 +31,6 @@
#include <cstdint> #include <cstdint>
#include <fstream> #include <fstream>
#include <iostream>
#include <iterator> #include <iterator>
#include <new> #include <new>
#include <string> #include <string>

View File

@ -3,6 +3,9 @@
#include "util/exception_utils.hpp" #include "util/exception_utils.hpp"
#include <boost/algorithm/string/case_conv.hpp> #include <boost/algorithm/string/case_conv.hpp>
#include <istream>
#include <string>
namespace osrm::storage namespace osrm::storage
{ {
std::istream &operator>>(std::istream &in, FeatureDataset &datasets) std::istream &operator>>(std::istream &in, FeatureDataset &datasets)

View File

@ -9,6 +9,7 @@
#include <cstdlib> #include <cstdlib>
#include <exception> #include <exception>
#include <iostream>
#include <new> #include <new>
#include <thread> #include <thread>

View File

@ -18,6 +18,7 @@
#include "util/mmap_tar.hpp" #include "util/mmap_tar.hpp"
#include "util/opening_hours.hpp" #include "util/opening_hours.hpp"
#include "util/static_rtree.hpp" #include "util/static_rtree.hpp"
#include "util/std_hash.hpp"
#include "util/string_util.hpp" #include "util/string_util.hpp"
#include "util/timezones.hpp" #include "util/timezones.hpp"
#include "util/timing_util.hpp" #include "util/timing_util.hpp"
@ -42,25 +43,6 @@
#include <tuple> #include <tuple>
#include <vector> #include <vector>
namespace std
{
template <typename T1, typename T2, typename T3> struct hash<std::tuple<T1, T2, T3>>
{
size_t operator()(const std::tuple<T1, T2, T3> &t) const
{
return hash_val(std::get<0>(t), std::get<1>(t), std::get<2>(t));
}
};
template <typename T1, typename T2> struct hash<std::tuple<T1, T2>>
{
size_t operator()(const std::tuple<T1, T2> &t) const
{
return hash_val(std::get<0>(t), std::get<1>(t));
}
};
} // namespace std
namespace osrm::updater namespace osrm::updater
{ {
namespace namespace

View File

@ -1,16 +1,8 @@
#include "util/coordinate_calculation.hpp"
#ifndef NDEBUG
#include "util/log.hpp"
#endif
#include "osrm/coordinate.hpp" #include "osrm/coordinate.hpp"
#ifndef NDEBUG #include "util/coordinate_calculation.hpp"
#include <bitset>
#endif #include <cstdint>
#include <iomanip>
#include <iostream>
#include <limits>
namespace osrm::util namespace osrm::util
{ {

View File

@ -9,6 +9,7 @@
#include <algorithm> #include <algorithm>
#include <iterator> #include <iterator>
#include <limits> #include <limits>
#include <optional>
#include <utility> #include <utility>
namespace osrm::util::coordinate_calculation namespace osrm::util::coordinate_calculation
@ -173,14 +174,14 @@ double computeAngle(const Coordinate first, const Coordinate second, const Coord
return angle; return angle;
} }
boost::optional<Coordinate> std::optional<Coordinate>
circleCenter(const Coordinate C1, const Coordinate C2, const Coordinate C3) circleCenter(const Coordinate C1, const Coordinate C2, const Coordinate C3)
{ {
// free after http://paulbourke.net/geometry/circlesphere/ // free after http://paulbourke.net/geometry/circlesphere/
// require three distinct points // require three distinct points
if (C1 == C2 || C2 == C3 || C1 == C3) if (C1 == C2 || C2 == C3 || C1 == C3)
{ {
return boost::none; return std::nullopt;
} }
// define line through c1, c2 and c2,c3 // define line through c1, c2 and c2,c3
@ -195,7 +196,7 @@ circleCenter(const Coordinate C1, const Coordinate C2, const Coordinate C3)
(std::abs(C2C1_lat) < std::numeric_limits<double>::epsilon() && (std::abs(C2C1_lat) < std::numeric_limits<double>::epsilon() &&
std::abs(C3C2_lat) < std::numeric_limits<double>::epsilon())) std::abs(C3C2_lat) < std::numeric_limits<double>::epsilon()))
{ {
return boost::none; return std::nullopt;
} }
else if (std::abs(C2C1_lon) < std::numeric_limits<double>::epsilon()) else if (std::abs(C2C1_lon) < std::numeric_limits<double>::epsilon())
{ {
@ -233,7 +234,7 @@ circleCenter(const Coordinate C1, const Coordinate C2, const Coordinate C3)
// can this ever happen? // can this ever happen?
if (std::abs(C2C1_slope - C3C2_slope) < std::numeric_limits<double>::epsilon()) if (std::abs(C2C1_slope - C3C2_slope) < std::numeric_limits<double>::epsilon())
return boost::none; return std::nullopt;
const double C1_y = static_cast<double>(toFloating(C1.lat)); const double C1_y = static_cast<double>(toFloating(C1.lat));
const double C1_x = static_cast<double>(toFloating(C1.lon)); const double C1_x = static_cast<double>(toFloating(C1.lon));
@ -247,7 +248,7 @@ circleCenter(const Coordinate C1, const Coordinate C2, const Coordinate C3)
(2 * (C3C2_slope - C2C1_slope)); (2 * (C3C2_slope - C2C1_slope));
const double lat = (0.5 * (C1_x + C2_x) - lon) / C2C1_slope + 0.5 * (C1_y + C2_y); const double lat = (0.5 * (C1_x + C2_x) - lon) / C2C1_slope + 0.5 * (C1_y + C2_y);
if (lon < -180.0 || lon > 180.0 || lat < -90.0 || lat > 90.0) if (lon < -180.0 || lon > 180.0 || lat < -90.0 || lat > 90.0)
return boost::none; return std::nullopt;
else else
return Coordinate(FloatLongitude{lon}, FloatLatitude{lat}); return Coordinate(FloatLongitude{lon}, FloatLatitude{lat});
} }

View File

@ -1,7 +1,5 @@
#include "util/exception.hpp" #include "util/exception.hpp"
#include <utility>
// This function exists to 'anchor' the class, and stop the compiler from // This function exists to 'anchor' the class, and stop the compiler from
// copying vtable and RTTI info into every object file that includes // copying vtable and RTTI info into every object file that includes
// this header. (Caught by -Wweak-vtables under Clang.) // this header. (Caught by -Wweak-vtables under Clang.)

View File

@ -17,7 +17,7 @@ NodeIdVectorToLineString::NodeIdVectorToLineString(
// converts a vector of node ids into a linestring geojson feature // converts a vector of node ids into a linestring geojson feature
util::json::Object util::json::Object
NodeIdVectorToLineString::operator()(const std::vector<NodeID> &node_ids, NodeIdVectorToLineString::operator()(const std::vector<NodeID> &node_ids,
const boost::optional<json::Object> &properties) const const std::optional<json::Object> &properties) const
{ {
util::json::Array coordinates; util::json::Array coordinates;
std::transform(node_ids.begin(), std::transform(node_ids.begin(),
@ -37,7 +37,7 @@ NodeIdVectorToMultiPoint::NodeIdVectorToMultiPoint(
util::json::Object util::json::Object
NodeIdVectorToMultiPoint::operator()(const std::vector<NodeID> &node_ids, NodeIdVectorToMultiPoint::operator()(const std::vector<NodeID> &node_ids,
const boost::optional<json::Object> &properties) const const std::optional<json::Object> &properties) const
{ {
util::json::Array coordinates; util::json::Array coordinates;
std::transform(node_ids.begin(), std::transform(node_ids.begin(),
@ -51,7 +51,7 @@ NodeIdVectorToMultiPoint::operator()(const std::vector<NodeID> &node_ids,
//---------------------------------------------------------------- //----------------------------------------------------------------
util::json::Object util::json::Object
CoordinateVectorToMultiPoint::operator()(const std::vector<util::Coordinate> &input_coordinates, CoordinateVectorToMultiPoint::operator()(const std::vector<util::Coordinate> &input_coordinates,
const boost::optional<json::Object> &properties) const const std::optional<json::Object> &properties) const
{ {
auto coordinates = makeJsonArray(input_coordinates); auto coordinates = makeJsonArray(input_coordinates);
return makeFeature("MultiPoint", std::move(coordinates), properties); return makeFeature("MultiPoint", std::move(coordinates), properties);
@ -60,7 +60,7 @@ CoordinateVectorToMultiPoint::operator()(const std::vector<util::Coordinate> &in
//---------------------------------------------------------------- //----------------------------------------------------------------
util::json::Object util::json::Object
CoordinateVectorToLineString::operator()(const std::vector<util::Coordinate> &input_coordinates, CoordinateVectorToLineString::operator()(const std::vector<util::Coordinate> &input_coordinates,
const boost::optional<json::Object> &properties) const const std::optional<json::Object> &properties) const
{ {
auto coordinates = makeJsonArray(input_coordinates); auto coordinates = makeJsonArray(input_coordinates);
return makeFeature("LineString", std::move(coordinates), properties); return makeFeature("LineString", std::move(coordinates), properties);

View File

@ -1,11 +1,7 @@
#include "util/guidance/turn_lanes.hpp" #include "util/guidance/turn_lanes.hpp"
#include <algorithm>
#include <iostream>
#include <tuple> #include <tuple>
#include <boost/assert.hpp>
namespace osrm::util::guidance namespace osrm::util::guidance
{ {
LaneTuple::LaneTuple() : lanes_in_turn(0), first_lane_from_the_right(INVALID_LANEID) LaneTuple::LaneTuple() : lanes_in_turn(0), first_lane_from_the_right(INVALID_LANEID)

View File

@ -5,13 +5,13 @@
#include <boost/filesystem/fstream.hpp> #include <boost/filesystem/fstream.hpp>
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
#include <boost/optional.hpp>
#include <rapidjson/document.h> #include <rapidjson/document.h>
#include <rapidjson/error/en.h> #include <rapidjson/error/en.h>
#include <rapidjson/istreamwrapper.h> #include <rapidjson/istreamwrapper.h>
#include <fstream> #include <fstream>
#include <optional>
#include <regex> #include <regex>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
@ -158,7 +158,7 @@ void Timezoner::LoadLocalTimesRTree(rapidjson::Document &geojson, std::time_t ut
rtree = rtree_t(polygons); rtree = rtree_t(polygons);
} }
boost::optional<struct tm> Timezoner::operator()(const point_t &point) const std::optional<struct tm> Timezoner::operator()(const point_t &point) const
{ {
std::vector<rtree_t::value_type> result; std::vector<rtree_t::value_type> result;
rtree.query(boost::geometry::index::intersects(point), std::back_inserter(result)); rtree.query(boost::geometry::index::intersects(point), std::back_inserter(result));
@ -168,6 +168,6 @@ boost::optional<struct tm> Timezoner::operator()(const point_t &point) const
if (boost::geometry::within(point, local_times[index].first)) if (boost::geometry::within(point, local_times[index].first))
return local_times[index].second; return local_times[index].second;
} }
return boost::none; return std::nullopt;
} }
} // namespace osrm::updater } // namespace osrm::updater

1
third_party/variant/.mason vendored Submodule

@ -0,0 +1 @@
Subproject commit 6adb140160cb549400f73ea35c1d9eb5782210e0

View File

@ -2,102 +2,123 @@ language: generic
sudo: false sudo: false
# Save common build configurations as shortcuts, so we can reference them later.
addons_shortcuts:
addons_clang35: &clang35
apt:
sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.5' ]
packages: [ 'clang-3.5', 'llvm-3.5-dev' ]
addons_clang36: &clang36
apt:
sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.6' ]
packages: [ 'clang-3.6' ]
addons_clang37: &clang37
apt:
sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.7' ]
packages: [ 'clang-3.7' ]
addons_clang38: &clang38
apt:
sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.8' ]
packages: [ 'clang-3.8']
addons_clang39: &clang39
apt:
sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise' ]
packages: [ 'clang-3.9']
addons_gcc47: &gcc47
apt:
sources: [ 'ubuntu-toolchain-r-test' ]
packages: [ 'g++-4.7' ]
addons_gcc48: &gcc48
apt:
sources: [ 'ubuntu-toolchain-r-test' ]
packages: [ 'g++-4.8' ]
addons_gcc49: &gcc49
apt:
sources: [ 'ubuntu-toolchain-r-test' ]
packages: [ 'g++-4.9' ]
addons_gcc5: &gcc5
apt:
sources: [ 'ubuntu-toolchain-r-test' ]
packages: [ 'g++-5' ]
matrix: matrix:
include: include:
# clang++ 4.0 via mason with -flto and -fsanitize=cfi
- os: linux
compiler: "clang++-40-mason"
env: CXX=clang++-4.0 CXXFLAGS="-flto -fsanitize=cfi -fvisibility=hidden" LDFLAGS="-flto -fsanitize=cfi -fvisibility=hidden"
addons:
apt:
sources: [ 'ubuntu-toolchain-r-test' ]
packages: [ 'libstdc++-4.9-dev' ]
before_install:
- git submodule update --init
- ./.mason/mason install clang++ 4.0.1
- export PATH=$(./.mason/mason prefix clang++ 4.0.1)/bin:${PATH}
- ./.mason/mason install binutils 2.27
- export PATH=$(./.mason/mason prefix binutils 2.27)/bin:${PATH}
# clang++ 4.0 via mason with -fsanitize=address
- os: linux
compiler: "clang++-40-mason"
env: CXX=clang++-4.0 CXXFLAGS="-fsanitize=address -fsanitize-address-use-after-scope -fno-omit-frame-pointer -fno-common" LDFLAGS="-fsanitize=address" ASAN_OPTIONS=check_initialization_order=1:detect_stack_use_after_return=1
sudo: required
addons:
apt:
sources: [ 'ubuntu-toolchain-r-test' ]
packages: [ 'libstdc++-4.9-dev' ]
before_install:
- git submodule update --init
- ./.mason/mason install clang++ 4.0.1
- export PATH=$(./.mason/mason prefix clang++ 4.0.1)/bin:${PATH}
# clang++ 4.0 via mason with -fsanitize=undefined
- os: linux
compiler: "clang++-40-mason"
env: CXX=clang++-4.0 CXXFLAGS="-fsanitize=undefined" LDFLAGS="-fsanitize=undefined"
addons:
apt:
sources: [ 'ubuntu-toolchain-r-test' ]
packages: [ 'libstdc++-4.9-dev' ]
before_install:
- git submodule update --init
- ./.mason/mason install clang++ 4.0.1
- export PATH=$(./.mason/mason prefix clang++ 4.0.1)/bin:${PATH}
# clang++ 4.0 via mason with -fsanitize=integer
- os: linux
compiler: "clang++-40-mason"
env: CXX=clang++-4.0 CXXFLAGS="-fsanitize=integer" LDFLAGS="-fsanitize=integer"
addons:
apt:
sources: [ 'ubuntu-toolchain-r-test' ]
packages: [ 'libstdc++-4.9-dev' ]
before_install:
- git submodule update --init
- ./.mason/mason install clang++ 4.0.1
- export PATH=$(./.mason/mason prefix clang++ 4.0.1)/bin:${PATH}
# clang++ 4.0 via mason with -fsanitize=safe-stack
- os: linux
compiler: "clang++-40-mason"
env: CXX=clang++-4.0 CXXFLAGS="-fsanitize=safe-stack" LDFLAGS="-fsanitize=safe-stack"
addons:
apt:
sources: [ 'ubuntu-toolchain-r-test' ]
packages: [ 'libstdc++-4.9-dev' ]
before_install:
- git submodule update --init
- ./.mason/mason install clang++ 4.0.1
- export PATH=$(./.mason/mason prefix clang++ 4.0.1)/bin:${PATH}
- os: osx - os: osx
osx_image: xcode7 osx_image: xcode8
env: TEST_GYP_BUILD=True env: OSX_OLDEST_SUPPORTED=10.7 TEST_GYP_BUILD=True
compiler: clang
- os: osx
osx_image: xcode8
env: OSX_OLDEST_SUPPORTED=10.12
compiler: clang compiler: clang
- os: linux - os: linux
compiler: "clang35" compiler: "clang35"
env: CXX=clang++-3.5 COVERAGE=True env: CXX=clang++-3.5 COVERAGE=True
addons: *clang35 addons:
apt:
sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.5' ]
packages: [ 'clang-3.5', 'libstdc++-4.9-dev' ]
- os: linux - os: linux
compiler: "clang36" compiler: "clang36"
env: CXX=clang++-3.6 env: CXX=clang++-3.6
addons: *clang36 addons:
- os: linux apt:
compiler: "clang37" sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.6' ]
env: CXX=clang++-3.7 packages: [ 'clang-3.6' ]
addons: *clang37
- os: linux
compiler: "clang38"
env: CXX=clang++-3.8
addons: *clang38
- os: linux
compiler: "clang38"
env: CXX=clang++-3.8 CXX_STD=c++14
addons: *clang38
# not whitelisted yet: https://github.com/travis-ci/apt-package-whitelist/issues/2764
#- os: linux
# compiler: "clang39"
# env: CXX=clang++-3.9
# addons: *clang39
- os: linux
compiler: "gcc47"
env: CXX=g++-4.7
addons: *gcc47
- os: linux - os: linux
compiler: "gcc48" compiler: "gcc48"
env: CXX=g++-4.8 env: CXX=g++-4.8
addons: *gcc48 addons:
apt:
sources: [ 'ubuntu-toolchain-r-test' ]
packages: [ 'g++-4.8' ]
- os: linux - os: linux
compiler: "gcc49" compiler: "gcc49"
env: CXX=g++-4.9 env: CXX=g++-4.9
addons: *gcc49 addons:
- os: linux apt:
compiler: "gcc49" sources: [ 'ubuntu-toolchain-r-test' ]
env: CXX=g++-4.9 CXX_STD=c++14 packages: [ 'g++-4.9' ]
addons: *gcc49
- os: linux - os: linux
compiler: "gcc5" compiler: "gcc5"
env: CXX=g++-5 CXXFLAGS="-D_GLIBCXX_USE_CXX11_ABI=0" env: CXX=g++-5
addons: *gcc5 addons:
apt:
sources: [ 'ubuntu-toolchain-r-test' ]
packages: [ 'g++-5' ]
- os: linux - os: linux
compiler: "gcc5" compiler: "gcc6"
env: CXX=g++-5 CXXFLAGS="-D_GLIBCXX_USE_CXX11_ABI=1" env: CXX=g++-6 CXX_STD=c++14
addons: *gcc5 addons:
apt:
sources: [ 'ubuntu-toolchain-r-test' ]
packages: [ 'g++-6' ]
before_install: install:
- echo ${CXX} - echo ${CXX}
- if [[ $(uname -s) == 'Linux' ]]; then - if [[ $(uname -s) == 'Linux' ]]; then
export PYTHONPATH=$(pwd)/.local/lib/python2.7/site-packages; export PYTHONPATH=$(pwd)/.local/lib/python2.7/site-packages;
@ -108,7 +129,17 @@ before_install:
PYTHONUSERBASE=$(pwd)/.local pip install --user cpp-coveralls; PYTHONUSERBASE=$(pwd)/.local pip install --user cpp-coveralls;
fi fi
install: script:
# Build in Release
- make
- make test
- make bench
- make sizes
- scripts/run_compilation_failure_tests.sh
- make clean;
# Build in Debug
- export BUILDTYPE=Debug
- make
- make test - make test
- make bench - make bench
- make sizes - make sizes
@ -118,11 +149,11 @@ install:
make gyp; make gyp;
fi fi
script: after_script:
- if [[ ${COVERAGE:-0} == 'True' ]]; then - if [[ ${COVERAGE:-0} == 'True' ]]; then
make clean; make clean;
make coverage; make coverage;
./out/cov-test; ./out/cov-test;
cp unit*gc* test/; cp unit*gc* test/;
./.local/bin/cpp-coveralls --gcov /usr/bin/llvm-cov-3.5 --gcov-options '\-lp' -i optional.hpp -i recursive_wrapper.hpp -i variant.hpp -i variant_io.hpp; ./.local/bin/cpp-coveralls --gcov /usr/bin/llvm-cov-3.5 --gcov-options '\-lp' -i optional.hpp -i recursive_wrapper.hpp -i variant.hpp -i variant_io.hpp variant_cast.hpp;
fi fi

420
third_party/variant/CHANGELOG.md vendored Normal file
View File

@ -0,0 +1,420 @@
# Variant changelog
## 1.2.0
Released: July 3, 2020
(82f9561)
* Use perfect forwarding for internal value types deductions (#178) (#180)
* Implement support for "moving" values out (#142) (#178) (#180)
* Preserve ability to specify explicit `return_type` in visitors (#181)
* Add self-assignment checks in copy and move assignment operator= (#164)
* Add relevant tests
## 1.1.6
Released: April 25, 2019
(a4f87dc)
* make type used for `type_index` configurable via `type_index_t` typdef + use `unsigned int` by default. This addresses `sizeof` discrepancies between boost/std/mapbox variants (ref #19) [view commit](http://github.com/mapbox/variant/commit/9eec1fd48947d81af3debb82686c593b15f79aad)
* use `mapbox::util::type_index_t` (#19) [view commit](http://github.com/mapbox/variant/commit/05ee9aca16c3968e34db3b241c44eecb981344e0)
* Ensure internal index type is capable of holding all alternatives (ref #138) [view commit](http://github.com/mapbox/variant/commit/fa8e124a2367abc9c06f7e83926691085eed45c0)
* Add compile time check to disallow array types as alternatives. [view commit](http://github.com/mapbox/variant/commit/3f6fd131ef07a091338cec81ec8d23d6ca44528d)
* Make `type_index_t` configurable at compile time via `MAPBOX_VARIANT_MINIMIZE_SIZE` and `MAPBOX_VARIANT_OPTIMIZE_FOR_SPEED`. Default is `unsigned int`. (ref #138) [view commit](http://github.com/mapbox/variant/commit/35487cd39400b9a4bd30a18e6dfbf9cb1aaa80cd)
* add missing <limits> [view commit](http://github.com/mapbox/variant/commit/c839c666c324306a252b0fbcadd31e80e02e2898)
* Adds a test for polymorphic lambdas in match, resolves #140 [view commit](http://github.com/mapbox/variant/commit/9ac8978f5125182ac1bd9a1b68533bf9695f7289)
* Merge pull request #138 from mapbox/sizeof [view commit](http://github.com/mapbox/variant/commit/3d807d31621d52a8b27494c8f80aa50f6464f17d)
* Merge pull request #141 from mapbox/match-otherwise [view commit](http://github.com/mapbox/variant/commit/916139a2e51e125816efce6e19d428385601273f)
* Update bundled Catch to v1.9.0 [view commit](http://github.com/mapbox/variant/commit/f9c265d7e7a188aa4437f534d4c0648af0118b51)
* REQUIRE_THROWS etc take an expression not a block [view commit](http://github.com/mapbox/variant/commit/a064940e2ce7e40ef5e4db5710b399c68a71be4b)
* Merge pull request #143 from tomhughes/catch [view commit](http://github.com/mapbox/variant/commit/550ac2f159ca883d360c196149b466955c77a573)
* Add static_variant_cast, dynamic_variant_cast [view commit](http://github.com/mapbox/variant/commit/51fccd755b05ee9d3dec9da239acd15d0823c381)
* Merge pull request #144 from narizhny/Casts [view commit](http://github.com/mapbox/variant/commit/291121f6ac682c6cc5a7a69f253492f03ca7324f)
* recursive_wrapper fail to compile when used with 2 classes which are base and derived #146 [view commit](http://github.com/mapbox/variant/commit/7a541ba10d2eb9a9da0f11bb27319cd125d43a3d)
* recursive_wrapper test - avoid constructing new functor in recursive calls, call itself via `this` pointer. [view commit](http://github.com/mapbox/variant/commit/ea106db54b167b8dce7c0b3b9b59bb06b209db33)
* Merge branch 'master' of https://github.com/BlueSolei/variant into BlueSolei-master [view commit](http://github.com/mapbox/variant/commit/195367cfc19e1e08933487fa7cc56cb7f6d25cc8)
* Merge branch 'BlueSolei-master' [view commit](http://github.com/mapbox/variant/commit/e01b7bf3334e788fb99f4a510d5bc87a4a581342)
* add test for ref #147 + https://github.com/mapbox/variant/pull/147 [view commit](http://github.com/mapbox/variant/commit/6247207595902dbf898a430346335af2a3485c74)
* - Add a project mapbox_variant. - Use of the 'os' module to capture CXX_STD. - Common configs moved to project. - Built targets moved to 'out' directory. [view commit](http://github.com/mapbox/variant/commit/b2471ffc74c163194943b17b2b2c5758c59655ca)
* - Remove the use of boost libraries. - Add default build. [view commit](http://github.com/mapbox/variant/commit/561a09dd005468f9cdef651030471a1215f1885f)
* - Use of the module 'os' to get BOOST_DIR. - Add macro SINGLE_THREADED to single threading mode. - Define single threading mode as default. - Add lambda_overload_test and hashable_test. [view commit](http://github.com/mapbox/variant/commit/bd0a2d559724b8daa7d1ff33df90976e26a595aa)
* - Add auxiliar rule exe-test. [view commit](http://github.com/mapbox/variant/commit/04a6797a6aa2a86dd3eb6517893255c010f6e524)
* Merge pull request #153 from ricardocosme/boost-build [view commit](http://github.com/mapbox/variant/commit/266f68d9f1c3ad65e6d6c264f0130bc4c652618a)
* Use forwarding reference in make_visitor and visitor [view commit](http://github.com/mapbox/variant/commit/9f991da78d3146d32be67695a89c2b1197c826b2)
* Add copy assignment and move assignment operators. [view commit](http://github.com/mapbox/variant/commit/f0b50062b4fd2bf2b86aeada2efa8e36cfa6cb1c)
* Merge pull request #154 from ricardocosme/forwarding_reference_make_visitor [view commit](http://github.com/mapbox/variant/commit/b78b51548743737357e5b3bbe296f465d5f4fdae)
* add CHANGELOG.md skeleton [view commit](http://github.com/mapbox/variant/commit/555436f715e5e0929a13664f0911ecc4931356d1)
* add <sha1> to CHANGELOG entries. [view commit](http://github.com/mapbox/variant/commit/6497bce683e6e8edf80f80bc4fed65235690b335)
* update CHANGELOG (git log <tag1>...<tag2> --pretty=format:'* %s [view commit](http://github.com/mapbox/variant/commit/%H)' --reverse) [view commit](http://github.com/mapbox/variant/commit/75bb549d233eb94c74d2730dc3a8d8ed35c87f3d)
* use full sha1 [view commit](http://github.com/mapbox/variant/commit/ba3085a5eb6e874d43432dc75f3392092e1e7214)
* add intial `variant_alternative` implementation (#161 http://en.cppreference.com/w/cpp/utility/variant/variant_alternative) [view commit](http://github.com/mapbox/variant/commit/43357808cc93e69d2975e31e68986137ac5e88c9)
* add lost test check + remove stderr [view commit](http://github.com/mapbox/variant/commit/4b98c485cf7d74691f7921145054641daa66936e)
* alternative implementation of `variant_alternative` [view commit](http://github.com/mapbox/variant/commit/3449d00cf525d8ef98cee0f4a276e2928398a8f9)
* add `variant_alternative_t` [view commit](http://github.com/mapbox/variant/commit/3ffef950b005f31961f167242911b2f97d2634c3)
* add optimized 'variant_alternative' implementation usinh built-in `__type_pack_element` when available (clang++) [view commit](http://github.com/mapbox/variant/commit/ae193141379c1706e17098c67c5b4e4f48b19c48)
* add compile index in range check for __type_pack_element branch. [view commit](http://github.com/mapbox/variant/commit/8b1de314711bff2f9f3c748ac0ed7cd7d6400331)
* fix preprocessor logic [view commit](http://github.com/mapbox/variant/commit/30560e19e60c23227b29bc3434a163d2343333d3)
* add `variant_size` helper [view commit](http://github.com/mapbox/variant/commit/835ebc19321c6a9696a2072b7fbd5ca3de818860)
* Merge pull request #162 from mapbox/variant_alternative [view commit](http://github.com/mapbox/variant/commit/237f83cad2c76b1717ba4076c30aca32339336a8)
* Removes deprecated static_visitor to avoid msvc C4996 compiler warning [view commit](http://github.com/mapbox/variant/commit/215d64585ef92e16f18f5da81195b0279f53f599)
* Merge pull request #163 from MaxRis/master [view commit](http://github.com/mapbox/variant/commit/859a8c933a0c2ab18941acb9dcf834799c0de46c)
* Fix README.md issues [view commit](http://github.com/mapbox/variant/commit/0888a8e92df4c1cfd85419b05910355b2d78013b)
* Merge pull request #165 from nick70/master [view commit](http://github.com/mapbox/variant/commit/5eee328d69aaa805bd0b43bdaede12a8eb4632eb)
* Fix the noexcept specifications for move assignment and conversion. [view commit](http://github.com/mapbox/variant/commit/9c81bef8cf285d9fb45f1eaf9b29eba4fee08d1b)
* Merge pull request #160 from mlogan/master [view commit](http://github.com/mapbox/variant/commit/256ddd55582bb7c06c342315dbacc6a42fee4b34)
* report actual file size not allocated size. [view commit](http://github.com/mapbox/variant/commit/ef3856c85f389d4be7feb6555336168c4adcfa0e)
* use `ls -lah` as `du -h --apparent-size` is not universally supported. [view commit](http://github.com/mapbox/variant/commit/a64062576d9af09469183a94b9770c8e7f877a93)
* fix Makefile [view commit](http://github.com/mapbox/variant/commit/502e32b8bade6e19d7fe511f4634e7033f61235f)
* try fixing travis via upgrading clang++ from 3.9.1 -> 4.0.1 [view commit](http://github.com/mapbox/variant/commit/f31bcfb4bc97cf4c5e89b01bbfa7df4cd553f576)
* steady .. downgrade clang++ to 4.0.0 [view commit](http://github.com/mapbox/variant/commit/11a36a9f12adc30ac47afc9681ec8aa1a2d68c28)
* update mason [view commit](http://github.com/mapbox/variant/commit/fe0a0666fc734033f6a9cd2256226eec5943138a)
* update mason + update clang++ to 4.0.1 [view commit](http://github.com/mapbox/variant/commit/c1a14e7d9e9a10ea7d793d83043d9a18b974ca8e)
* Run ASAN builda in isolated VM via `sudo : required` [view commit](http://github.com/mapbox/variant/commit/5a5ecca5bef02072109a714bab840a36ea772f01)
* Merge pull request #167 from mapbox/clang++4 [view commit](http://github.com/mapbox/variant/commit/0f734f01e685a298e3756d30044a4164786c58c5)
* Moved to in-class initialization [view commit](http://github.com/mapbox/variant/commit/2fef61f08e44bcc99b1acc21ea78554b08d8f6e7)
* Merge pull request #171 from mapbox/jrex-mute-clang-analyzer [view commit](http://github.com/mapbox/variant/commit/0305fdb2a462ca39db7b8cce189561bed17b48
## 1.1.5
Released: January 7, 2017
(d2588a8f1d6b5d480d228e6d8a906ce634bdea9a)
* add package.json for publishing to npm [view commit](http://github.com/mapbox/variant/commit/cb5635ba2556d76aaba97e4d0fc14b82b48f8b61)
* test with clang 3.9 and g++-6 [view commit](http://github.com/mapbox/variant/commit/efa75df2735d3f5a5fa2646528d4006bf9b5b3dc)
* travis: fix addons [view commit](http://github.com/mapbox/variant/commit/ce2eea64499cd37eec7932ddf82f72b9f1a1b79e)
* makefile improvements [view commit](http://github.com/mapbox/variant/commit/c81b475b40797d503f18ddad4c065f6b1694d341)
* upgrade boost to 1.62.0 [view commit](http://github.com/mapbox/variant/commit/b9c58d631a22e97f4069a819765f5c157525df6a)
* upgrade mason [view commit](http://github.com/mapbox/variant/commit/a760cea8dab53e587498470861b364f1256a5e0d)
* test clang++ via mason [view commit](http://github.com/mapbox/variant/commit/84eeb54c9408297db4bc57e3ea5a1b3d9f075a66)
* fix clang++ PATH [view commit](http://github.com/mapbox/variant/commit/e07a533a8f451fe541db683fc713eb0012730115)
* disable clang++ 3.9, will work on getting working in a branch [view commit](http://github.com/mapbox/variant/commit/702826365d1ea13710b82949c254af5920c92999)
* test with clang++ sanitizers and flto [view commit](http://github.com/mapbox/variant/commit/9b2de45460f4df3a22c6607043d50df730dd42af)
* fix LDFLAGS [view commit](http://github.com/mapbox/variant/commit/20d693ed9a04cc6b689f4c6a1ed58c96f964b08a)
* -fsanitize=cfi and -fsanitize=safe-stack [view commit](http://github.com/mapbox/variant/commit/d1bb6e54608c6bfe3970b2653971da49b3c15ef8)
* more sanitizer options [view commit](http://github.com/mapbox/variant/commit/4fe5ced5db2cb46b23a6e326b5bf9292d95c0642)
* re-enable older compilers, trim excess [view commit](http://github.com/mapbox/variant/commit/6317a0b7406395729139327a83a71cfa14513fac)
* avoid expensive instantiation of tuple constructor in noexcept [view commit](http://github.com/mapbox/variant/commit/4febf973c2a0fc297869d78fc82368a16ee7f4fb)
* Merge pull request #132 from lightmare/avoid-tuple-instantiation [view commit](http://github.com/mapbox/variant/commit/18919174da93165a79ca5fdbfde4b172182c6156)
* enable -Werror, suppress warnings from non variant headers using isystem [view commit](http://github.com/mapbox/variant/commit/253047f53549c3fb1df441859cfd42aecc9f3a8f)
* fix conversion warnings [view commit](http://github.com/mapbox/variant/commit/539d712746d08a172e68a47f7aa73ffdda40b70b)
* build in both release and debug on travis [view commit](http://github.com/mapbox/variant/commit/cf9a534991b5a36f86674975768e0a1600c776be)
* fortification flags + -pthreads for linux where needed [view commit](http://github.com/mapbox/variant/commit/886377de081dd8099ef4a7869ae3ff5d6c850c8d)
* try without pthreads [view commit](http://github.com/mapbox/variant/commit/1023f2d9adcf0a14be7cb729abab8156ecd962c5)
* limit some flags to clang++ [view commit](http://github.com/mapbox/variant/commit/904dcaee6d0d872eae52578e38199577418f9a32)
* Add -pthread [view commit](http://github.com/mapbox/variant/commit/b433986199b7dfbe59fa498eb80791a49c625170)
* upgrade libstdc++ for coverage build [view commit](http://github.com/mapbox/variant/commit/7b409402c3cf4a0260aa36ee768ee474aa3683c1)
* drop -Wstack-protector which gives unhelpful warnings [view commit](http://github.com/mapbox/variant/commit/c8ec829ffb4498a0aea8ffa9b62ba4932cdefbdf)
* disable -Wparentheses for older gcc [view commit](http://github.com/mapbox/variant/commit/a80beaafc20c2c015ace5fb1e4c99f6de8c24d75)
* Merge pull request #133 from mapbox/Werror [view commit](http://github.com/mapbox/variant/commit/a9707c3de095c715f84a1855684a3dc8e37a594a)
* remove useless and/or dubious compiler flags [view commit](http://github.com/mapbox/variant/commit/5141d8d21a5b648e9fef879bfc12b29ffac7288d)
* Merge pull request #134 from lightmare/warnings [view commit](http://github.com/mapbox/variant/commit/18a8055fef0e14110c313ca358f0f7c88290bed0)
* osx: test that will support both latest (10.12) and oldest with c++11 support: 10.7 [view commit](http://github.com/mapbox/variant/commit/4923eb527c129060ba970d622d639ad2ada42497)
* fix gyp build [view commit](http://github.com/mapbox/variant/commit/5baa948fa73313091bc082b9f3d17c5b5f600cac)
* upgrade to llvm 3.9.1 [view commit](http://github.com/mapbox/variant/commit/f5fb4661ebf1ecd0167bce50b00a8339604395b0)
* upgrade mason [view commit](http://github.com/mapbox/variant/commit/61f8acea1b09de639b46c8af0c5aae29f51dd05c)
* Merge pull request #135 from mapbox/llvm-3.9.1 [view commit](http://github.com/mapbox/variant/commit/05b7612aa86c28f95d39ba786c7b611e811e4bf8)
* Trivial missing comma in README example code [view commit](http://github.com/mapbox/variant/commit/d2588a8f1d6b5d480d228e6d8a906ce634bdea9a)
## 1.1.4
Released: December 21, 2016
(02bd1ac4c07e6db9fe0f01267853e43b41637b74)
* Provides Convenient Lambda Overload Visitor Interface, resolves #113. [view commit](http://github.com/mapbox/variant/commit/d09188640b6d5a637f391108f849a962d02dbb40)
* Removes ::type Usage [view commit](http://github.com/mapbox/variant/commit/2275a61974aaf117fa8d08c08d640ffd05935db8)
* Adds C++14 SFINAE Test [view commit](http://github.com/mapbox/variant/commit/4d462f27b2d852f66a3769e5983691c0f9233c9e)
* Merge branch 'daniel-j-h-lambda-visitor' [view commit](http://github.com/mapbox/variant/commit/9a115c5eb3c09509c70a57b25b283b6e1cbba919)
* Makes variant<Ts...> hashable iff Ts... are hashable, closes #125 [view commit](http://github.com/mapbox/variant/commit/97d0379f0afc87cd74a10be56fbccfa04785f568)
* Implements Pattern Matching for Sum Types via `.match` Member Function. [view commit](http://github.com/mapbox/variant/commit/720c23736bb318937d0f53a413a617ff05040b73)
* Adds Documentation for Readme, resolves #98 [view commit](http://github.com/mapbox/variant/commit/d0266436b18ea3b1f15c8a244985b57a0a2b3770)
* Merge pull request #126 from daniel-j-h/hashable [view commit](http://github.com/mapbox/variant/commit/3c17c37aea0d7e3d9e860b746d54160ec820e6a2)
* Merge pull request #128 from daniel-j-h/match [view commit](http://github.com/mapbox/variant/commit/ed84def128ed99a4b3b1ebcde278be7f761e782e)
* Merge pull request #129 from daniel-j-h/docs [view commit](http://github.com/mapbox/variant/commit/02bd1ac4c07e6db9fe0f01267853e43b41637b74)
## 1.1.3
Released: October 24, 2016
(a5a79a594f39d705a7ef969f54a0743516f0bc6d)
* use C++17 disjunction for no-references and one-convertible tests [view commit](http://github.com/mapbox/variant/commit/2c7ddecdb7ec3b1c1a6bc1797528375e513b7ab0)
* Merge pull request #116 from lightmare/disjunction [view commit](http://github.com/mapbox/variant/commit/8e2f6964157885f1655c1673d65f3aea9b90fe18)
* Update README [view commit](http://github.com/mapbox/variant/commit/aaddee9270e3956cee98cdd7d04aea848d69f5f0)
* expose `using types = std::tuple<Types...>;` - useful for adapting variant to `boost::spirit` (QI,Karma,X3) [view commit](http://github.com/mapbox/variant/commit/e5818212a8f7ef89df0aa76d5244eca78b8dbb8d)
* add `struct adapted_variant_tag;` [view commit](http://github.com/mapbox/variant/commit/173a7457952d0f24e2c55d5eb3ea785ad41639fb)
* Merge pull request #120 from mapbox/types [view commit](http://github.com/mapbox/variant/commit/84a426a31ad3b63c4b8f8d189841e19af48cda40)
* nicer stderr [view commit](http://github.com/mapbox/variant/commit/9b46167f5c42a19a3b66cb92eb60418486b4e424)
* Fix #122 by adding an extra compile check in universal ctor (via @lightmare) + test case [view commit](http://github.com/mapbox/variant/commit/a5a79a594f39d705a7ef969f54a0743516f0bc6d)
## 1.1.2
Released: July 26, 2016
(388376ac9f0102feba2d2122873b08e15a66a879)
* Re-implement type matching logic to reject ambigious conversions [view commit](http://github.com/mapbox/variant/commit/71ac8fdf96e547dca34fe58c5cd8d1dce2ef0dac)
* update tests [view commit](http://github.com/mapbox/variant/commit/8be6a2aa8f85e1455198eff31a577a1fb95e1d46)
* comment out code [view commit](http://github.com/mapbox/variant/commit/075d9636fdfe563b535fa3ba087409f940c018e4)
* Merge pull request #114 from mapbox/strict-conversions [view commit](http://github.com/mapbox/variant/commit/388376ac9f0102feba2d2122873b08e15a66a879)
## 1.1.1
Released: July 18, 2016
(c511b2f34d966c09e02a1b833db33a9a1f9b2196)
## 1.1.0
Released: February 11, 2016
(5aab5df0dc899b484c04ce9c649645787ee0bc5c)
* remove erroneous `;` ref #96 [view commit](http://github.com/mapbox/variant/commit/3f025adbf599d8dd9bfca02d45b37e49a2cae841)
* fix coverage to avoid warning: unit.gcno:version '402*', prefer '406*' [view commit](http://github.com/mapbox/variant/commit/b0ee4729bfc9ea649abe40f279de384df75b79d1)
* fix clang 3.8 compile, try 3.9 [view commit](http://github.com/mapbox/variant/commit/f034d5571de987d14b404dba94e7269ac41fa583)
* remove invalid option for llvm-cov [view commit](http://github.com/mapbox/variant/commit/5f6ed7149d737edf9f1f019beb54cbe5289c474c)
* run coverage with clang 3.5 - fix clang 3.8 build [view commit](http://github.com/mapbox/variant/commit/82bb901b6cc0de8c238a07292163dc7c28a26ce4)
* issue warning `-Wweak-vtables` so this issue is not forgotten (https://github.com/mapbox/variant/issues/95) [view commit](http://github.com/mapbox/variant/commit/35ca16c74f5712afb4f042f45ea64078fa0b630e)
* move headers into include/mapbox folder - closes #99 [view commit](http://github.com/mapbox/variant/commit/f00b24bf65e8af7fddc56ac4a3abe67ed974b0a5)
* Update README.md [view commit](http://github.com/mapbox/variant/commit/13c631a6297d9abc9677c1afc1a3907fec7c16b4)
* Add include directory [view commit](http://github.com/mapbox/variant/commit/7e4a01189bb4050524954b2a88c82de7cb82ea4a)
* Merge branch 'master' into include [view commit](http://github.com/mapbox/variant/commit/9bd902536f533305186aaf70edb2f0b9713f6b6b)
* fix typo [view commit](http://github.com/mapbox/variant/commit/a606e90243dcf145cf06d46e8e30c447f85af178)
* ammend include dir [view commit](http://github.com/mapbox/variant/commit/343831611e60e324e311d67f05da953e357df0a1)
* update remaining `<variant.hpp>` to `<mapbox/variant.hpp>` [view commit](http://github.com/mapbox/variant/commit/bfe0f19dd14dedad9c0a6f1e211e81bd1233564e)
* fix compilation [view commit](http://github.com/mapbox/variant/commit/390229a59703d2467347d62f3e134e67ea6835cc)
* Merge pull request #101 from mapbox/include [view commit](http://github.com/mapbox/variant/commit/1bc46e525a9dec71af28f822e5fc031c1352ad2e)
* Remove Xcode 6 from CI matrix [view commit](http://github.com/mapbox/variant/commit/9b2fc858ccd84509fd7164a4847e7dc95e58d5a5)
* Install boost with mason; eliminate boost::timer dependency [view commit](http://github.com/mapbox/variant/commit/04dc3a46b02d6b8714d00280bb85c88716727862)
* `is<T>()` - add specialisation for recursive_wrapper<T> + update tests (ref #102) [view commit](http://github.com/mapbox/variant/commit/c6ae1ea0acf8c4392a806ad3abd5b11eb3b8a8ce)
* remove expected error string - current implementation emits compiler specific error message e.g [view commit](http://github.com/mapbox/variant/commit/4368d75292ae5149034b59b483fc3f8b3956a839)
* Jamroot - add missing include directory ./test/include for auto_cpu_timer.hpp [view commit](http://github.com/mapbox/variant/commit/7f7470fee6a42c3c68f1fa359a28cf762df385c3)
* Update README.md [view commit](http://github.com/mapbox/variant/commit/8bdad6b6d73844ef8437f004654c0745f0cec96a)
* Fix building with GCC (g++-5.2.0) on OS X (Darwin) (ref #108) [view commit](http://github.com/mapbox/variant/commit/55579f03fba747500b3a105ae73a7dfe6059cfc1)
* Update README.md [view commit](http://github.com/mapbox/variant/commit/33e27ec4c7cc5e1669f2181d13eacdfff15dfb61)
* Merge pull request #109 from mapbox/darwin-build-flags [view commit](http://github.com/mapbox/variant/commit/2f8a4a381f2ad8f9c2d3d068a757a3e0e9994495)
* Add get_unchecked<T>() to enable use with exceptions disabled [view commit](http://github.com/mapbox/variant/commit/434dab048d52e4141146bb95fdabdf7aa62e799b)
* remove unused internal metafunctions [view commit](http://github.com/mapbox/variant/commit/48d60445cca1d71fbebb6456b5d45a18bb9cb3b8)
* add static which<T>() function to get a contained types' which value [view commit](http://github.com/mapbox/variant/commit/74ce146d9b96081965d5fcdf53feefab6199468c)
* Merge branch 'master' into 111-which-constexpr [view commit](http://github.com/mapbox/variant/commit/dca3d967c165de1d0fb3bb5e1c2d6b4bcd76782f)
* Merge branch '111-which-constexpr' [view commit](http://github.com/mapbox/variant/commit/bb8c2d20317191f5228341a87b0c362c4d15be5b)
* variant - yield return type of mapbox::util::get<T> automatically and make interface consistent (addresses #82) [view commit](http://github.com/mapbox/variant/commit/adf0e02bceb74339b8ccc3e9e3f316917cb3cc22)
* uncomment tests ref #82 [view commit](http://github.com/mapbox/variant/commit/37acc5a7caef10d2f52dbdcee71be53b79dda027)
* Merge pull request #110 from mapbox/110-get_unchecked [view commit](http://github.com/mapbox/variant/commit/20e44accb1edf84d944d44f91ed7401198368aae)
* c++ apply formatting [view commit](http://github.com/mapbox/variant/commit/372d7c88fe796a138d0e578328914ac80e5a949a)
* use local HAS_EXCEPTIONS #define (__EXCEPTIONS is g++/clang specific macro) [view commit](http://github.com/mapbox/variant/commit/eedafd31f9fdbaffcb605d8d34a3a3443a4f7a2d)
* update .mason pkgs [view commit](http://github.com/mapbox/variant/commit/b5728ad76e1402c130a9330aa44b6f4b655b13b4)
* fix value_traits to be able to match T, T& and T const& to the direct type stored in variant (ref #112) [view commit](http://github.com/mapbox/variant/commit/b3a002d185afac295486e2ebd6b84c78a2267ba0)
* add test for b3a002d185afac295486e2ebd6b84c78a2267ba0 (ref #112) [view commit](http://github.com/mapbox/variant/commit/c511b2f34d966c09e02a1b833db33a9a1f9b2196)
## 1.0
Released: April 1, 2015
(bf485dfb59aef26f3ef2183d7c8c1111ad97062b)
* Initial commit [view commit](http://github.com/mapbox/variant/commit/9b82890ea11742eafd686f44b8cc7075029dbd7b)
* initial import [view commit](http://github.com/mapbox/variant/commit/bb95645b86a8fe427df9af799ecd139e4fab38ef)
* remove unused boost::static_visitor [view commit](http://github.com/mapbox/variant/commit/2dbc79fdd28c2ad9623c6516069ae616af11cdc5)
* call reserve in boost::variant test and change order [view commit](http://github.com/mapbox/variant/commit/9c1d245388396ac289ccee238b549e48a7916f9e)
* add readme and makefile [view commit](http://github.com/mapbox/variant/commit/5afa5b2e1756dfb0e332f3e11bffdfb33cd31f75)
* makefile fixups [view commit](http://github.com/mapbox/variant/commit/c627c07afc972b3f1bab3ca219416d6e918cd39b)
* turn on more aggressive warnings and fix them where appropriate [view commit](http://github.com/mapbox/variant/commit/20ee8ffe2889f9e0f4974ba2aba028ccd3ce347a)
* -Wsign-compare [view commit](http://github.com/mapbox/variant/commit/12ef94a8c0edb897858b82d0064093e251ac4024)
* remove unneeded headers [view commit](http://github.com/mapbox/variant/commit/eeba005f2f2e287f23661e9dd555e57e0365d22c)
* include <stdexcept> [view commit](http://github.com/mapbox/variant/commit/a7b562eb0ef665b57e3a29a2ff83721bc3f66a03)
* include headers for new/size_t/move [view commit](http://github.com/mapbox/variant/commit/c3963a96aab7d3d2e380652e4268c5d729778a59)
* add sizes target to check object sizes [view commit](http://github.com/mapbox/variant/commit/a1685041726cba13aa9fb728ec4963f3e7872200)
* add tests [view commit](http://github.com/mapbox/variant/commit/df1d00cc50d3b5a1cce203305d52f536f622663c)
* interleave test runs to ensure first run penalty does not murky the results [view commit](http://github.com/mapbox/variant/commit/969a346db6ab41adb66f7b3cbbcc92cd15c3b339)
* add to gitignore [view commit](http://github.com/mapbox/variant/commit/e98fc0736064d3131a25e899420b41276e801a45)
* fix build on ubuntu/g++-4.8 [view commit](http://github.com/mapbox/variant/commit/b8ab4b8c6beb2d0d4bb2afc9fda901c83588d153)
* debug/release builds + profiling [view commit](http://github.com/mapbox/variant/commit/a25c3597deb4d889085bc9492d2cf4f6df847a5a)
* pass release flags to make sizes [view commit](http://github.com/mapbox/variant/commit/23f112ae5e551a731939e8220a16a6c7a29d844b)
* force inlining to reduce final object size (yes **reduce**, with clang++ at least) [view commit](http://github.com/mapbox/variant/commit/c65aa114402e8f7b1d44062ff973f7c807741d06)
* optimization: avoid overhead of function call for invalid type check [view commit](http://github.com/mapbox/variant/commit/cebd6a31e54d84811cccab62991d142aa8aacbad)
* test threaded [view commit](http://github.com/mapbox/variant/commit/5a84ea2f40ccd2cadbc1091fae05b37b1d69c85c)
* 10 threads [view commit](http://github.com/mapbox/variant/commit/c06ebf15268925ef5e0f3ce763db13fd0c27ef2b)
* use perfect forwarding instead of move [view commit](http://github.com/mapbox/variant/commit/cd81aed73c9f1176e26090abc60a9d2467f5d5bf)
* const as const can. also reimplementation of operator= to allow for ADL in swap [view commit](http://github.com/mapbox/variant/commit/33603114129c387c5938287f1839f852a8f3a5f2)
* Merge pull request #1 from artemp/consts_and_fwds [view commit](http://github.com/mapbox/variant/commit/dff07459931e6d76b4eea6092041cbf247e01f64)
* implement comparison operators (==,<) implement operator<< [view commit](http://github.com/mapbox/variant/commit/cb9374b1ebb4c2da42e06af71ca738e9316b0582)
* make THREADS=4 ( we want to test variant not an operating system, better still make it config (TODO)) add simple test for operator== and operator<< ( define VARIANT_LOGICAL_TESTS to enable) [view commit](http://github.com/mapbox/variant/commit/68aa114c5d06a979b8fb31f0cdd2647833544cb1)
* c++ : better names (#2) [view commit](http://github.com/mapbox/variant/commit/48dd83308ebb5ab21c295499948d27d42801b306)
* c++ : better names (#2) [view commit](http://github.com/mapbox/variant/commit/46f40479fd02170b9d4bf48655a6a6a7845d77cc)
* Merge branch 'master' of github.com:artemp/variant [view commit](http://github.com/mapbox/variant/commit/41d5626bee25a4edd36c2e2d05bde46751417baa)
* Added const [view commit](http://github.com/mapbox/variant/commit/9d7afc7362e095acf032b5a3d2057d960157ffcb)
* Fixed var names [view commit](http://github.com/mapbox/variant/commit/7423b70b907b640b477c9675d79b43abb6bf21ed)
* changing const keyword position to 'T const &' [view commit](http://github.com/mapbox/variant/commit/f6677d163a1c1df6d960baa7d0d7983edac95cc3)
* Add -march=native to release build flags, implies -mtune=.. [view commit](http://github.com/mapbox/variant/commit/3ff69626f348da3f6827fc1573e014400d5f6813)
* Merge pull request #7 from artemp/const_correctness_part2 [view commit](http://github.com/mapbox/variant/commit/f8ff1da09fdb3902b39cb6893fda048b2760da68)
* Merge pull request #8 from artemp/architecture-optimizations [view commit](http://github.com/mapbox/variant/commit/4b325da289df3e91bc32d71d4adceb28d3cf8215)
* fix remaining names [view commit](http://github.com/mapbox/variant/commit/2de14db6a431689e07630f42ee18a30101ed11b3)
* add -march=native to Jamroot [view commit](http://github.com/mapbox/variant/commit/8c03239ed115ed51d181ea52a40f0e9e8ec73f42)
* more name fixing ref #2 [view commit](http://github.com/mapbox/variant/commit/f27bd4c7f514f9f646eb0766cfd8f4b7e8f0ed33)
* structs dont have private members [view commit](http://github.com/mapbox/variant/commit/3d0072d34600bbf2fc21bee3db65770cf6796402)
* add pgo option to Makefile [view commit](http://github.com/mapbox/variant/commit/7f4f85e93d09630dd78ba5eb113bb03fb9804979)
* Merge pull request #9 from artemp/classes_and_structs [view commit](http://github.com/mapbox/variant/commit/21ced9474d93a96bb5c7cd527efa5e0ba742e84a)
* Merge pull request #10 from artemp/profile_guided_optimization [view commit](http://github.com/mapbox/variant/commit/0fc8f6b3911b6b6c0dbe72d5c440c7c094add899)
* + implement binary visitation [view commit](http://github.com/mapbox/variant/commit/943b24689b918f13ee1bdeb43111cbdf49139797)
* more realistic test [view commit](http://github.com/mapbox/variant/commit/e481fdb58ac2fec43a18ba119715f539ba000007)
* fix return types [view commit](http://github.com/mapbox/variant/commit/b41b4f69c21e552198310ebaf17c4776e2b4dc1f)
* Return uint64_t [view commit](http://github.com/mapbox/variant/commit/de6db67da287a8f80b956c85a5a6bff2af6cd52f)
* recursive_wrapper init impl [view commit](http://github.com/mapbox/variant/commit/f1c12747d921763288435beb53fbf23eafb6100d)
* Merge branch 'master' of github.com:artemp/variant [view commit](http://github.com/mapbox/variant/commit/49274509129f7f5957cc785b82771ad772fb2478)
* + add static_visitor requirement to ease return_type deduction [view commit](http://github.com/mapbox/variant/commit/80d999a3471b5647a17c14217ef237f8e9f82543)
* fix binary visitor test [view commit](http://github.com/mapbox/variant/commit/87207d76fb81f87b0bbde00c1ed44ec6043103fa)
* use static_visitor as a base class for all visitors [view commit](http://github.com/mapbox/variant/commit/48f78bcd767b99575a5af4aeb0490342e8a2b7a9)
* recursive_wrapper test (work-in-progress) [view commit](http://github.com/mapbox/variant/commit/05af9c4f21eefc91c713bc1e34e0e04b0556519a)
* include recursive_wrapper [view commit](http://github.com/mapbox/variant/commit/cbd9e2cf91e58baebd79ce336ba4b20148f303af)
* update test (FIXME - inteface is very clunky atm and needs more work) [view commit](http://github.com/mapbox/variant/commit/d2cda9a88684d2e7fad3d3527e53f7c64c84378e)
* unwrap recursive_wrapper [view commit](http://github.com/mapbox/variant/commit/bc65cb8d7be23806dc63c2adf03fc8e9b5557f66)
* + const [view commit](http://github.com/mapbox/variant/commit/6e9a10f43eab476d68399d6dcc51a2464cd2f0b8)
* recursive variant test using std::unique_ptr move semantics [view commit](http://github.com/mapbox/variant/commit/5ebf86772daade4490652218e3437d5d0ca7d1de)
* add missing test file [view commit](http://github.com/mapbox/variant/commit/b4abfa58efb676aa86a3dd2dfee04f7e95aee7fd)
* update recursive_wrapper and unique_ptr tests to accept <num-iter> arg [view commit](http://github.com/mapbox/variant/commit/edcb444afc193784cb6237616d68973b36e7920e)
* make test -> make bench [view commit](http://github.com/mapbox/variant/commit/fc80297390285e83394983201473d01edfa17d4c)
* fix compile of test/variant [view commit](http://github.com/mapbox/variant/commit/da417016e6af968cdcea1b2ec9f2023d3ee77cad)
* recursive_wrapper.hpp depends on boost checked delete for the moment [view commit](http://github.com/mapbox/variant/commit/a8d019d470e11eb3a569581ce140397bb6f6e31d)
* shuffle code, all build targets in out/ directory [view commit](http://github.com/mapbox/variant/commit/8e5abd0f14e298b9cc93f7428c2cd21ce732fad9)
* all tests in ./test directory [view commit](http://github.com/mapbox/variant/commit/dadea1f2a7d9c08e1a5979cc5bb824779fb73380)
* add travis [view commit](http://github.com/mapbox/variant/commit/7e775d10774261b5461474013b840fdd899db023)
* fix travis targets [view commit](http://github.com/mapbox/variant/commit/c6bd4f8131f6a58d6d6dfaf3017c8793a0da9819)
* travis: upgrade to gcc-4.8 for c++11 support [view commit](http://github.com/mapbox/variant/commit/84fdc9e2c0701980c083ff3cb8701f3076f10fa6)
* fix a few -Wsign-compare warnings [view commit](http://github.com/mapbox/variant/commit/d3d0704c59dba67f925b707d6c72babadd607ce9)
* fix -Wshadow warning [view commit](http://github.com/mapbox/variant/commit/e19d0e5aca3b4e4a76e29e34352d634b7c495202)
* fix linux compile of binary_visitor_test.cpp [view commit](http://github.com/mapbox/variant/commit/d8df077f29428c55688910d5f96e79b6d351d5e1)
* qualify c++11 int types [view commit](http://github.com/mapbox/variant/commit/62e7165925bfce3e4c11a2fce1cad8d486825613)
* fix #12 [view commit](http://github.com/mapbox/variant/commit/c0593af2c3066d13f30bf15241da313539539f18)
* test with both gcc 4.7 and 4.8 [view commit](http://github.com/mapbox/variant/commit/916719bb38cec2e9f4ff7c3d2ef480734badbb7d)
* Add BSD license [view commit](http://github.com/mapbox/variant/commit/cf7f7bef518d7dd67d74e84bdbaf40a6c5826114)
* add unit tests [view commit](http://github.com/mapbox/variant/commit/0ef558f9607844fa88b1857e6ff993121dd84d71)
* port logical tests to test/unit.cpp - refs #15 [view commit](http://github.com/mapbox/variant/commit/7109df9c4f423b846839240d720de4a89be101c8)
* version, starting at 0.1.0 [view commit](http://github.com/mapbox/variant/commit/e5c89779e59bc22571ce5beb27a823b94b2be786)
* try building on windows with gyp [view commit](http://github.com/mapbox/variant/commit/b97876a2e5ddaf8931cecd36b5a649fb3e1eb420)
* call gyp_main.py [view commit](http://github.com/mapbox/variant/commit/24cddfbc76c713046b130158c72231bd827d4a23)
* be explicit about config and platform [view commit](http://github.com/mapbox/variant/commit/bc80b31f8c4afd469f65046cfc3fe18bba95fbd3)
* also test building with gyp on travis [view commit](http://github.com/mapbox/variant/commit/51eda4f439c24223a964fe25d077ff1efa27dce0)
* try 'any cpu' [view commit](http://github.com/mapbox/variant/commit/41056fa781bf3c6a79182db338595b44d6370c25)
* put msbuild on path [view commit](http://github.com/mapbox/variant/commit/948a6ccb89ae2b4a3682805519b585bf573763a9)
* appveyor: try building 32 bit [view commit](http://github.com/mapbox/variant/commit/1b89ab841021d28da193e3b1fab27269651bdc17)
* Update README.md [view commit](http://github.com/mapbox/variant/commit/011b5125a4bb139f794bb37080bd33cae6519f7c)
* + it breaks builds for me - I have 'using clang ..' in $(boost-dir)/tools/build/v2/user-config.jam where it should be. [view commit](http://github.com/mapbox/variant/commit/1b2fc49bbc7e76bbaf2c64ea44cb3f287d5948a5)
* ```apply_visitor``` interface not-compatible with boost::apply_visitor (by changing args order) wasn't smart [view commit](http://github.com/mapbox/variant/commit/67ac560672e5ea7bf99a4a823b5259ccd6d1bd5d)
* fix syntax [view commit](http://github.com/mapbox/variant/commit/002ccdcde4aacfcc6b67ad4981c05402514c09f1)
* windows support [view commit](http://github.com/mapbox/variant/commit/64f8fb4473f3ef6f7117dc02f02a20645e415b72)
* update readme [view commit](http://github.com/mapbox/variant/commit/20f26eceebef717a0ee759b42bfe939a95874807)
* appeveyor: try building for just x86 [view commit](http://github.com/mapbox/variant/commit/b3f8117d05071981106b7d1fe15405a318d3c1df)
* fix setting of msbuild_toolset for c++11 support [view commit](http://github.com/mapbox/variant/commit/d0603d41a8597089c0c1cd099ebb8bcf5e1414d3)
* Add vcbuild.bat [view commit](http://github.com/mapbox/variant/commit/bb12b87574fcdaa7bdca6c1529d442eab2d52b97)
* remove sizeof checks since they are implementation depedenent [view commit](http://github.com/mapbox/variant/commit/f5af06c20329a0c762af9420a3ae2e3d22c02c91)
* comment failing test on windows [view commit](http://github.com/mapbox/variant/commit/7d4dc68667659e7585d28f743509956e92759255)
* appveyor: re-enable matrix [view commit](http://github.com/mapbox/variant/commit/6dbc0546bdab9e8dc291eb08d2e6dce13a0dcfe8)
* add <utility> to be include order agnostic [view commit](http://github.com/mapbox/variant/commit/9be8c519c67ef2ec8d3b5a7b736f0a8b870b43ed)
* Merge pull request #16 from DennisOSRM/master [view commit](http://github.com/mapbox/variant/commit/b27a14e98d9eadf2aabd628a602f9e4a5fcb0a5f)
* move detail tests + add initial comments (@artemp, please review) [view commit](http://github.com/mapbox/variant/commit/ea25e84aeec16588857ac83c1241d34a5df4adac)
* fix typo in code comment [skip ci] [view commit](http://github.com/mapbox/variant/commit/b773421f5868315eccd504204f32ee8c02e78dc6)
* rename internal id to index, add tests [view commit](http://github.com/mapbox/variant/commit/390e2315b97bbc71aa575d98bacc1ed760d0aa4a)
* Merge pull request #18 from mapbox/type_index [view commit](http://github.com/mapbox/variant/commit/046296a95c9d34224c23c843bc8bd6d502f81b47)
* modify tests slightly to output num_iter ((3+2)-4) [view commit](http://github.com/mapbox/variant/commit/602eceb753751ae30cd5ca7a25d3337179ba6b5e)
* boost is uneeded for unit.cpp tests [view commit](http://github.com/mapbox/variant/commit/e1de3d78e8827d5b6819cc91b430429a46093c95)
* enable ctor's for valid types at compile time [view commit](http://github.com/mapbox/variant/commit/31e3fd96fe4f86d9ac5ac53d6e3e07605307eb5c)
* [travis] multi-os [view commit](http://github.com/mapbox/variant/commit/2f1e36d25f152c31cc3b2673946a8670dd189e74)
* fix path to boost/variant.hpp on linux [view commit](http://github.com/mapbox/variant/commit/b31579c99042d36672fa9eefb09bcdb01e1bcc0a)
* move variant and friends into mapbox namespace for easy integration [view commit](http://github.com/mapbox/variant/commit/df55ab6ef48d1a28c58e409d71b3ee4b416cdf31)
* fix namespace [view commit](http://github.com/mapbox/variant/commit/397ed9c90bc55bbf2f3331f43a707789869d064a)
* inline accessors/setters [view commit](http://github.com/mapbox/variant/commit/2ebabd9b6cb1b95605b01708899498ac70b84201)
* default ctor : initialise with default contructed first type in parameters pack [view commit](http://github.com/mapbox/variant/commit/4d038f1462698c0977e14eacfd9abeb8da95c852)
* add default ctor test [view commit](http://github.com/mapbox/variant/commit/d7fa62b52f771f0d194441b5889409e792eff740)
* c++11 : use type aliases instead of typedefs [view commit](http://github.com/mapbox/variant/commit/03eb4c7d287b72eb43d2b6456ef38437c8c0ac34)
* converting operator= [view commit](http://github.com/mapbox/variant/commit/0eed7c3c1477e0673d379336b0745606d2780d8f)
* avoid wrapped object copying [view commit](http://github.com/mapbox/variant/commit/f7648ba392aea548fe0d583ceee2048ad57e2f54)
* fix move ctor + housekeeping [view commit](http://github.com/mapbox/variant/commit/6aee8c4a7543e0d38f64a07d67aaf394bea704d9)
* add <string> [view commit](http://github.com/mapbox/variant/commit/82cc6e2335b377b5e61e9a3bc974e619658ab515)
* remove unused header [view commit](http://github.com/mapbox/variant/commit/74425f135a6b7cdd49d86d2dd84cf9bdfe9154c2)
* uncomment to test single threaded [view commit](http://github.com/mapbox/variant/commit/7296d18458e2dbfc7ddb39f0fe5b96962c264dc6)
* fix bug : assign correct index (in reverse order of args) e.g first type is sizeof...(Types) - 1 [view commit](http://github.com/mapbox/variant/commit/7eb748eb65729c2d91a7c4f16e5bd56eb3038bdd)
* fix default ctor unit test [view commit](http://github.com/mapbox/variant/commit/03af9e421b36e17a9b873cb24347f6bad7c3dc6d)
* [gyp] fix typo in Windows release targets [view commit](http://github.com/mapbox/variant/commit/2d8ca78704f69c6498a0e689222588275c8f33aa)
* add non-const visitor interface (#22) [view commit](http://github.com/mapbox/variant/commit/54d07c9d336c989fe3c1231bbb7f6465ebc68da2)
* add unary_visitor test [view commit](http://github.com/mapbox/variant/commit/3b31c34368613c4cd101e6f7ee9677c2c7b6b75e)
* support implicit type convertions [view commit](http://github.com/mapbox/variant/commit/724a40baec3ded142c631b66521502840d8d183f)
* update to use recursive_wrapper<T> -> T conversions [view commit](http://github.com/mapbox/variant/commit/7e609812f15cbf41fab978fd3222c6029a5b67eb)
* unit test : update to use latest variant impl [view commit](http://github.com/mapbox/variant/commit/d1392fa431b5b5dac99cdb8b937ec05e13d98847)
* Mapbox name without the inner uppercase B. [view commit](http://github.com/mapbox/variant/commit/4e11d41723af714895c90cb8b9798527c946b2b4)
* Fix typo in comment. [view commit](http://github.com/mapbox/variant/commit/01509c76c30bea7a6bfffd0e59f9bbdbae8f1026)
* Formatting fixes. [view commit](http://github.com/mapbox/variant/commit/cfd7d991b23b2ecc659d18f22a2f78a05074450c)
* Use formatting "TYPE const&". [view commit](http://github.com/mapbox/variant/commit/9253ffdda65bd41ed21f9328a20a335fa0f5d582)
* Remove superfluous and inconsistent whitespace. [view commit](http://github.com/mapbox/variant/commit/d855ba8672fc5f439594325663899564f0632c94)
* Add comments for closing namespaces. [view commit](http://github.com/mapbox/variant/commit/3c2d662abb352bd429777251ddc613e751e49123)
* Merge branch 'joto-master' [view commit](http://github.com/mapbox/variant/commit/49e9f351a7a8d5615f8fb5ae2d4840042fc95bcc)
* Fix typos, whitespace and test tags. [view commit](http://github.com/mapbox/variant/commit/a12326984f323d10648115d94ace0b510d097b06)
* Add tests for implicit conversion and exceptions for wrong types. [view commit](http://github.com/mapbox/variant/commit/12c70938b00215ce86e48657d60a650dbfd8966e)
* Add test for printer visitor. [view commit](http://github.com/mapbox/variant/commit/fd470a6fde0941407a74c3d544c009eac0579e4f)
* Add test case for issue #25. [view commit](http://github.com/mapbox/variant/commit/74f1c5d9b02788fb9524ae674d43fdf07671d9cc)
* fix appveyor link in readme [view commit](http://github.com/mapbox/variant/commit/d49f82efb7689b8bc67be30633dd7f41b54f2e5a)
* Remove the need for the static_visitor class. [view commit](http://github.com/mapbox/variant/commit/e9283622a33231500c8cc3d1f27358d431c1e8a2)
* msvs: also define _DEBUG for debug builds [view commit](http://github.com/mapbox/variant/commit/c4bb359f883b568a88d5be8b3e4ce5c45626d71f)
* [appveyor] more debug flags [view commit](http://github.com/mapbox/variant/commit/b852c8d386e59a145a6b684d036ee7e327d0efe2)
* [appveyor][gyp] correct msvs_settings usage [view commit](http://github.com/mapbox/variant/commit/1f707864e37c305779e3398006b20e2ee5f14866)
* customize release builds [view commit](http://github.com/mapbox/variant/commit/4661a3c06b3738c7564c18474577d4faece6613a)
* [gyp][windows] add exception handling/rtti [view commit](http://github.com/mapbox/variant/commit/02556c9c317834ad3f05aa88dacc072ad9a63c99)
* use numeric values in valid range to avoid overflowing [view commit](http://github.com/mapbox/variant/commit/854c5a7a115d92b67698f3654d915edd483456b9)
* Removed wrong comments. [view commit](http://github.com/mapbox/variant/commit/8b6c0b34b76144d697ede0f386f1ea2f9c6ae2d1)
* Removed test case. [view commit](http://github.com/mapbox/variant/commit/08a7e04e3cf3ebd54e289201b1bd3d85225248ee)
* allow explicit un-initilised variant ctor [view commit](http://github.com/mapbox/variant/commit/d99139d4dee3ae4fa2b7465000d08fc5f5907e82)
* add boost::variant compatible accessors [view commit](http://github.com/mapbox/variant/commit/2afd3415cc28b8b7184e2750ac90e739c078b335)
* more verbose output to test script [view commit](http://github.com/mapbox/variant/commit/0c8b6b736788718ed28a0676cdb0b390249d5540)
* variant : make operator<< stricter to avoid unexpected instantiations [view commit](http://github.com/mapbox/variant/commit/76027798360405d910f8af9d6ae873fa5905be13)
* Add details on advantages of Mapbox variant [view commit](http://github.com/mapbox/variant/commit/a5ee02b2aacb0109725c611beaafc27dce89c12d)
* remove unneeded header [view commit](http://github.com/mapbox/variant/commit/73da70737f0e55b2276173ca923eb91bd8ae4f32)
* less debug info in release mode [view commit](http://github.com/mapbox/variant/commit/607ed1344f8117000e03da0b8bfb9268a1f826ee)
* rough cut of an optional type [view commit](http://github.com/mapbox/variant/commit/9badbd0fa37863240cf678be61116003d345a20a)
* add operator* and a static assert against reference types [view commit](http://github.com/mapbox/variant/commit/1141292eeed4a95f3e54c85e98f9ded180f84f32)
* Merge pull request #30 from DennisOSRM/optional [view commit](http://github.com/mapbox/variant/commit/32f971794c643d11f5bf374caef44cee295cdf7d)
* remove some whitespace [view commit](http://github.com/mapbox/variant/commit/f4bcf3ff733acbd4a798f1e9a5f80d5422bc9b79)
* explicit operator bool() const noexcept [view commit](http://github.com/mapbox/variant/commit/c77d98b3e8d06714ed0b0c288cd9ad457f2708c4)
* rename none_t -> none_type, move to private member of optional [view commit](http://github.com/mapbox/variant/commit/43e2e9a943555c09ce6ffb9c825a64bff229a3a6)
* remove instantiation of none_type as per @kkaefer's suggestion [view commit](http://github.com/mapbox/variant/commit/7242396fb5468defba37afd03e7a633075fa51ce)
* remove none_type and its complicated typedef from detail namespace, add it as private member class to optional [view commit](http://github.com/mapbox/variant/commit/c5f720515ad21fe3913fc841ea427ebdd1fa4c68)
* guard against self-assignment [view commit](http://github.com/mapbox/variant/commit/10a039c78b58857f8793dae3b0359cf1d6fb11ef)
* add unit tests for optional type [view commit](http://github.com/mapbox/variant/commit/607c6332cb96261a43a16fa94aea5d034ae58aac)
* Merge pull request #31 from mapbox/optional [view commit](http://github.com/mapbox/variant/commit/4cdd805a04175248b221753a0974de15c8f5b397)
* reformat optional.hpp to be more legible and less linty [view commit](http://github.com/mapbox/variant/commit/54e1dfe7631207da3f6a2bbc895c5240592ea5ea)
* universal-references: template <typename T> variant(T && val) {} it turned out we don't need a separate converting copy ctor (fixes windows compiler) [view commit](http://github.com/mapbox/variant/commit/82df4ed9cd2a8335c7e50b913f827216604dab07)
* Merge pull request #32 from mapbox/universal-references [view commit](http://github.com/mapbox/variant/commit/804fb6f370a35eaea3e273ebfcb2f92ef7379e91)
* use std::forward<T> for perfect forwarding (via @DennisOSRM) [view commit](http://github.com/mapbox/variant/commit/eb995158362307cea98e36eb782dd4ae63593d0f)
* fix assignment of optionals, adds a unit test [view commit](http://github.com/mapbox/variant/commit/f69f317069523cb6994fa9d594240deeb537753c)
* Merge pull request #33 from mapbox/fix_assignment_operator [view commit](http://github.com/mapbox/variant/commit/c56af229af98b71ba8ef637f3237cab828f0ec14)
* readme improvements [view commit](http://github.com/mapbox/variant/commit/5b8972b6ebcd095f35b810c43639785235218bbd)
* Merge branch 'master' into result_of [view commit](http://github.com/mapbox/variant/commit/4900027d0f66a7c701e22c667e92ce7b7521a73c)
* cast lhs to rhs type to avoid signed/unsigned comparisons warnings [view commit](http://github.com/mapbox/variant/commit/17074a3de539256ccab3871033df33c9d387dcbf)
* attempting to fix travis [view commit](http://github.com/mapbox/variant/commit/4fb9bd65ac4a204f8721f9528df9c14907a151f9)
* Merge branch 'master' into result_of [view commit](http://github.com/mapbox/variant/commit/fbcc50b57e58460e0cd90a232673271eff72311c)
* make deriving from static_visitor and providing result_type an option [view commit](http://github.com/mapbox/variant/commit/76ab6d4aa54664d7f8849695896ca57f4984bed0)
* Merge branch 'result_of' [view commit](http://github.com/mapbox/variant/commit/3cc2d708e0552ba4ebce11d4d67f798813f15aa2)
* fix automatic return_type calculation - ref #35 [view commit](http://github.com/mapbox/variant/commit/00ab88117ed25f78cdca2faa00beea0061271e85)
* test either g++ or clang++ [view commit](http://github.com/mapbox/variant/commit/199b3eca054075319a1978f09bdd77f9ff42e681)
* try adding code coverage / coveralls upload [view commit](http://github.com/mapbox/variant/commit/11e65282e335ed4a50bf261d21b8194230787ed8)
* fix bash syntax [view commit](http://github.com/mapbox/variant/commit/2fbfcd33998992df4d77f329e7a75c864616d0ab)
* add recursive wrapper to coverage [view commit](http://github.com/mapbox/variant/commit/f87a1cf10d62814d3bf4e72ac260a92e483ffb25)
* move operator<< into separate header <variant_io.hpp> [view commit](http://github.com/mapbox/variant/commit/24dcab23c4f70e54838e4a32a228aba8045ae17b)
* add coverage report [view commit](http://github.com/mapbox/variant/commit/89f8a41a4da81c2a01d39f83cf52e61997ce76ba)
* clean up coverage files in test directory too [skip ci] [view commit](http://github.com/mapbox/variant/commit/7dfdfa271e43780aff640852a632e88443b6fe32)
* add get<T>() overloads for when T is stored in recursive_wrapper<T> also makes get<T>() a compile time error where T is not in Types... (ref #24) [view commit](http://github.com/mapbox/variant/commit/36f1e12f66570f2a1f04535dc0ac0485d48e2bbe)
* update unit test to match c64c74775a80474f2012c1a49ab2865e3666107a [view commit](http://github.com/mapbox/variant/commit/c117592337cc20c238d4ce9f9d8847aff0cd55ab)
* add which() method returning zero based index of stored T in Types... for boost::variant() compatibility [view commit](http://github.com/mapbox/variant/commit/3b02ca0e3ab1a36dd6ec9138e7f93eb3176ae5f7)
* add reference_wrapper test [view commit](http://github.com/mapbox/variant/commit/5a2d5c5f292ae2d6128d02e7ee2b3b3d72facfc2)
* remove boost variant header [view commit](http://github.com/mapbox/variant/commit/c53422fb2d4e44b7e276fcde65498b603f429a2f)
* add support for 'unwrapping' std::reference_wrapper<T> and accessing std::reference_wrapper<T>::type through get<T>() + update test [view commit](http://github.com/mapbox/variant/commit/587519521ae0d9a24f997ab2dff77f13309aa5d2)
* pass F (functor) by ref/const ref [view commit](http://github.com/mapbox/variant/commit/2e0ce4a86d0b9d0ff9855838349fb599b15a274a)
* pass by const ref in 'apply_const' [view commit](http://github.com/mapbox/variant/commit/a3014f54651b71e25d81fbeaf99f29d63c625703)
* Revert "pass by const ref in 'apply_const'" [view commit](http://github.com/mapbox/variant/commit/e031c53d0c876ecf2b9d4a6e0a5383bd4169df71)
* Revert "pass F (functor) by ref/const ref" [view commit](http://github.com/mapbox/variant/commit/bf485dfb59aef26f3ef2183d7c8c1111ad97062b)

View File

@ -1,78 +1,62 @@
# Unofficial and incomplete build file using Boost build system. # Unofficial and incomplete build file using Boost build system.
# You should use make unless you know what you are doing. # You should use make unless you know what you are doing.
local BOOST_DIR = "/usr/local" ; import os ;
local boost_dir = [ os.environ BOOST_DIR ] ;
if ! $(boost_dir)
{
boost_dir = "/usr/local" ;
}
#using clang : : ; #using clang : : ;
lib system : : <name>boost_system <search>$(BOOST_DIR)/lib ; local cxx_std = [ os.environ CXX_STD ] ;
lib timer : chrono : <name>boost_timer <search>$(BOOST_DIR)/lib ; if ! $(cxx_std)
lib chrono : system : <name>boost_chrono <search>$(BOOST_DIR)/lib ; {
cxx_std = c++11 ;
}
exe variant-test project mapbox_variant
: : requirements
test/bench_variant.cpp <cxxflags>-std=$(cxx_std)
.//system <include>$(boost_dir)/include
.//timer <include>include
.//chrono <include>test/include
:
<include>$(BOOST_DIR)/include
<include>./include
<include>./test/include
#<define>SINGLE_THREADED
<variant>release:<cxxflags>"-march=native -Wweak-vtables"
;
exe binary-visitor-test
:
test/binary_visitor_test.cpp
.//system
.//timer
.//chrono
:
<include>$(BOOST_DIR)/include
<include>./include
<include>./test/include
<variant>release:<cxxflags>-march=native <variant>release:<cxxflags>-march=native
<threading>single:<define>SINGLE_THREADED
: default-build
<variant>release
<optimization>speed
<threading>single
; ;
exe recursive-wrapper-test rule exe-test ( name : reqs * : deps * )
: {
test/recursive_wrapper_test.cpp exe $(name)
.//system : test/$(name).cpp
.//timer : $(reqs)
.//chrono : $(deps)
: ;
<include>$(BOOST_DIR)/include explicit $(name) ;
<include>./include }
<include>./test/include
<variant>release:<cxxflags>-march=native exe-test bench_variant
: <variant>release:<cxxflags>-Wweak-vtables
; ;
exe unique-ptr-test exe-test binary_visitor_test ;
: exe-test recursive_wrapper_test ;
test/unique_ptr_test.cpp exe-test unique_ptr_test ;
.//system exe-test reference_wrapper_test ;
.//timer exe-test lambda_overload_test ;
.//chrono exe-test hashable_test ;
:
<include>$(BOOST_DIR)/include
<include>./include
<include>./test/include
<variant>release:<cxxflags>-march=native
;
install out
exe reference_wrapper_test : bench_variant
: binary_visitor_test
test/reference_wrapper_test.cpp unique_ptr_test
.//system reference_wrapper_test
.//timer lambda_overload_test
.//chrono hashable_test
:
<include>$(BOOST_DIR)/include
<include>./include
<include>./test/include
<variant>release:<cxxflags>-march=native
; ;

View File

@ -1,23 +1,53 @@
MASON = .mason/mason MASON = .mason/mason
BOOST_VERSION = boost 1.60.0 BOOST_VERSION = 1.62.0
CXX := $(CXX) CXX := $(CXX)
CXX_STD ?= c++11 CXX_STD ?= c++11
BOOST_FLAGS = `$(MASON) cflags $(BOOST_VERSION)` BOOST_ROOT = $(shell $(MASON) prefix boost $(BOOST_VERSION))
RELEASE_FLAGS = -O3 -DNDEBUG -march=native -DSINGLE_THREADED -fvisibility-inlines-hidden BOOST_FLAGS = -isystem $(BOOST_ROOT)/include/
DEBUG_FLAGS = -O0 -g -DDEBUG -fno-inline-functions RELEASE_FLAGS = -O3 -DNDEBUG -march=native -DSINGLE_THREADED -fvisibility-inlines-hidden -fvisibility=hidden
COMMON_FLAGS = -Wall -pedantic -Wextra -Wsign-compare -Wsign-conversion -Wshadow -Wunused-parameter -std=$(CXX_STD) DEBUG_FLAGS = -O0 -g -DDEBUG -fno-inline-functions -fno-omit-frame-pointer -fPIE
WARNING_FLAGS = -Werror -Wall -Wextra -pedantic \
-Wformat=2 -Wsign-conversion -Wshadow -Wunused-parameter
COMMON_FLAGS = -std=$(CXX_STD)
COMMON_FLAGS += $(WARNING_FLAGS)
CXXFLAGS := $(CXXFLAGS) CXXFLAGS := $(CXXFLAGS)
LDFLAGS := $(LDFLAGS) LDFLAGS := $(LDFLAGS)
export BUILDTYPE ?= Release
OS := $(shell uname -s)
ifeq ($(OS), Linux)
EXTRA_FLAGS = -pthread
endif
ifeq ($(OS), Darwin)
OSX_OLDEST_SUPPORTED ?= 10.7
# we need to explicitly ask for libc++ otherwise the
# default will flip back to libstdc++ for mmacosx-version-min < 10.9
EXTRA_FLAGS = -stdlib=libc++ -mmacosx-version-min=$(OSX_OLDEST_SUPPORTED)
endif
ifeq ($(BUILDTYPE),Release)
FINAL_CXXFLAGS := $(COMMON_FLAGS) $(RELEASE_FLAGS) $(CXXFLAGS) $(EXTRA_FLAGS)
else
FINAL_CXXFLAGS := $(COMMON_FLAGS) $(DEBUG_FLAGS) $(CXXFLAGS) $(EXTRA_FLAGS)
endif
ALL_HEADERS = $(shell find include/mapbox/ '(' -name '*.hpp' ')') ALL_HEADERS = $(shell find include/mapbox/ '(' -name '*.hpp' ')')
all: out/bench-variant out/unique_ptr_test out/unique_ptr_test out/recursive_wrapper_test out/binary_visitor_test out/lambda_overload_test out/hashable_test all: out/bench-variant out/unique_ptr_test out/unique_ptr_test out/recursive_wrapper_test out/binary_visitor_test out/lambda_overload_test out/hashable_test
mason_packages: $(MASON):
git submodule update --init .mason git submodule update --init .mason
$(MASON) install $(BOOST_VERSION)
mason_packages/headers/boost: $(MASON)
$(MASON) install boost $(BOOST_VERSION)
./deps/gyp: ./deps/gyp:
git clone --depth 1 https://chromium.googlesource.com/external/gyp.git ./deps/gyp git clone --depth 1 https://chromium.googlesource.com/external/gyp.git ./deps/gyp
@ -25,35 +55,35 @@ mason_packages:
gyp: ./deps/gyp gyp: ./deps/gyp
deps/gyp/gyp --depth=. -Goutput_dir=./ --generator-output=./out -f make deps/gyp/gyp --depth=. -Goutput_dir=./ --generator-output=./out -f make
make V=1 -C ./out tests make V=1 -C ./out tests
./out/Release/tests ./out/$(BUILDTYPE)/tests
out/bench-variant-debug: Makefile mason_packages test/bench_variant.cpp out/bench-variant-debug: Makefile mason_packages/headers/boost test/bench_variant.cpp
mkdir -p ./out mkdir -p ./out
$(CXX) -o out/bench-variant-debug test/bench_variant.cpp -I./include -Itest/include -pthreads $(DEBUG_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS) $(CXX) -o out/bench-variant-debug test/bench_variant.cpp -I./include -isystem test/include $(FINAL_CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS)
out/bench-variant: Makefile mason_packages test/bench_variant.cpp out/bench-variant: Makefile mason_packages/headers/boost test/bench_variant.cpp
mkdir -p ./out mkdir -p ./out
$(CXX) -o out/bench-variant test/bench_variant.cpp -I./include -Itest/include $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS) $(CXX) -o out/bench-variant test/bench_variant.cpp -I./include -isystem test/include $(FINAL_CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS)
out/unique_ptr_test: Makefile mason_packages test/unique_ptr_test.cpp out/unique_ptr_test: Makefile mason_packages/headers/boost test/unique_ptr_test.cpp
mkdir -p ./out mkdir -p ./out
$(CXX) -o out/unique_ptr_test test/unique_ptr_test.cpp -I./include -Itest/include $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS) $(CXX) -o out/unique_ptr_test test/unique_ptr_test.cpp -I./include -isystem test/include $(FINAL_CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS)
out/recursive_wrapper_test: Makefile mason_packages test/recursive_wrapper_test.cpp out/recursive_wrapper_test: Makefile mason_packages/headers/boost test/recursive_wrapper_test.cpp
mkdir -p ./out mkdir -p ./out
$(CXX) -o out/recursive_wrapper_test test/recursive_wrapper_test.cpp -I./include -Itest/include $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS) $(CXX) -o out/recursive_wrapper_test test/recursive_wrapper_test.cpp -I./include -isystem test/include $(FINAL_CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS)
out/binary_visitor_test: Makefile mason_packages test/binary_visitor_test.cpp out/binary_visitor_test: Makefile mason_packages/headers/boost test/binary_visitor_test.cpp
mkdir -p ./out mkdir -p ./out
$(CXX) -o out/binary_visitor_test test/binary_visitor_test.cpp -I./include -Itest/include $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS) $(CXX) -o out/binary_visitor_test test/binary_visitor_test.cpp -I./include -isystem test/include $(FINAL_CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS)
out/lambda_overload_test: Makefile mason_packages test/lambda_overload_test.cpp out/lambda_overload_test: Makefile mason_packages/headers/boost test/lambda_overload_test.cpp
mkdir -p ./out mkdir -p ./out
$(CXX) -o out/lambda_overload_test test/lambda_overload_test.cpp -I./include -Itest/include $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS) $(CXX) -o out/lambda_overload_test test/lambda_overload_test.cpp -I./include -isystem test/include $(FINAL_CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS)
out/hashable_test: Makefile mason_packages test/hashable_test.cpp out/hashable_test: Makefile mason_packages/headers/boost test/hashable_test.cpp
mkdir -p ./out mkdir -p ./out
$(CXX) -o out/hashable_test test/hashable_test.cpp -I./include -Itest/include $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS) $(CXX) -o out/hashable_test test/hashable_test.cpp -I./include -isystem test/include $(FINAL_CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS)
bench: out/bench-variant out/unique_ptr_test out/unique_ptr_test out/recursive_wrapper_test out/binary_visitor_test bench: out/bench-variant out/unique_ptr_test out/unique_ptr_test out/recursive_wrapper_test out/binary_visitor_test
./out/bench-variant 100000 ./out/bench-variant 100000
@ -63,13 +93,31 @@ bench: out/bench-variant out/unique_ptr_test out/unique_ptr_test out/recursive_w
out/unit.o: Makefile test/unit.cpp out/unit.o: Makefile test/unit.cpp
mkdir -p ./out mkdir -p ./out
$(CXX) -c -o $@ test/unit.cpp -Itest/include $(DEBUG_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(CXX) -c -o $@ test/unit.cpp -isystem test/include $(FINAL_CXXFLAGS)
out/%.o: test/t/%.cpp Makefile $(ALL_HEADERS) out/%.o: test/t/%.cpp Makefile $(ALL_HEADERS)
mkdir -p ./out mkdir -p ./out
$(CXX) -c -o $@ $< -Iinclude -Itest/include $(DEBUG_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(CXX) -c -o $@ $< -Iinclude -isystem test/include $(FINAL_CXXFLAGS)
out/unit: out/unit.o \
out/binary_visitor_1.o \
out/binary_visitor_2.o \
out/binary_visitor_3.o \
out/binary_visitor_4.o \
out/binary_visitor_5.o \
out/binary_visitor_6.o \
out/issue21.o \
out/issue122.o \
out/mutating_visitor.o \
out/optional.o \
out/recursive_wrapper.o \
out/sizeof.o \
out/unary_visitor.o \
out/variant.o \
out/variant_alternative.o \
out/nothrow_move.o \
out/visitor_result_type.o \
out/unit: out/unit.o out/binary_visitor_1.o out/binary_visitor_2.o out/binary_visitor_3.o out/binary_visitor_4.o out/binary_visitor_5.o out/binary_visitor_6.o out/issue21.o out/issue122.o out/mutating_visitor.o out/optional.o out/recursive_wrapper.o out/sizeof.o out/unary_visitor.o out/variant.o
mkdir -p ./out mkdir -p ./out
$(CXX) -o $@ $^ $(LDFLAGS) $(CXX) -o $@ $^ $(LDFLAGS)
@ -78,14 +126,14 @@ test: out/unit
coverage: coverage:
mkdir -p ./out mkdir -p ./out
$(CXX) -o out/cov-test --coverage test/unit.cpp test/t/*.cpp -I./include -Itest/include $(DEBUG_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(CXX) -o out/cov-test --coverage test/unit.cpp test/t/*.cpp -I./include -isystem test/include $(FINAL_CXXFLAGS) $(LDFLAGS)
sizes: Makefile sizes: Makefile
mkdir -p ./out mkdir -p ./out
@$(CXX) -o ./out/our_variant_hello_world.out include/mapbox/variant.hpp -I./include $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) && du -h ./out/our_variant_hello_world.out @$(CXX) -o ./out/our_variant_hello_world.out include/mapbox/variant.hpp -I./include $(FINAL_CXXFLAGS) && ls -lah ./out/our_variant_hello_world.out
@$(CXX) -o ./out/boost_variant_hello_world.out `$(MASON) prefix boost 1.60.0`/include/boost/variant.hpp -I./include $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(BOOST_FLAGS) && du -h ./out/boost_variant_hello_world.out @$(CXX) -o ./out/boost_variant_hello_world.out $(BOOST_ROOT)/include/boost/variant.hpp -I./include $(FINAL_CXXFLAGS) $(BOOST_FLAGS) && ls -lah ./out/boost_variant_hello_world.out
@$(CXX) -o ./out/our_variant_hello_world ./test/our_variant_hello_world.cpp -I./include $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) && du -h ./out/our_variant_hello_world @$(CXX) -o ./out/our_variant_hello_world ./test/our_variant_hello_world.cpp -I./include $(FINAL_CXXFLAGS) && ls -lah ./out/our_variant_hello_world
@$(CXX) -o ./out/boost_variant_hello_world ./test/boost_variant_hello_world.cpp -I./include $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(BOOST_FLAGS) && du -h ./out/boost_variant_hello_world @$(CXX) -o ./out/boost_variant_hello_world ./test/boost_variant_hello_world.cpp -I./include $(FINAL_CXXFLAGS) $(BOOST_FLAGS) && ls -lah ./out/boost_variant_hello_world
profile: out/bench-variant-debug profile: out/bench-variant-debug
mkdir -p profiling/ mkdir -p profiling/
@ -102,8 +150,8 @@ clean:
rm -f *.gcda *.gcno rm -f *.gcda *.gcno
pgo: out Makefile pgo: out Makefile
$(CXX) -o out/bench-variant test/bench_variant.cpp -I./include $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS) -pg -fprofile-generate $(CXX) -o out/bench-variant test/bench_variant.cpp -I./include $(FINAL_CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS) -pg -fprofile-generate
./test-variant 500000 >/dev/null 2>/dev/null ./test-variant 500000 >/dev/null 2>/dev/null
$(CXX) -o out/bench-variant test/bench_variant.cpp -I./include $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS) -fprofile-use $(CXX) -o out/bench-variant test/bench_variant.cpp -I./include $(FINAL_CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS) -fprofile-use
.PHONY: sizes test .PHONY: sizes test

View File

@ -9,13 +9,13 @@ An header-only alternative to `boost::variant` for C++11 and C++14
## Introduction ## Introduction
Variant's basic building blocks are: Variant's basic building blocks are:
- `variant<Ts...>` - a type-safe representation for sum-types / discriminated unions - `variant<Ts...>` - a type-safe representation for sum-types / discriminated unions
- `recursive_wrapper<T>` - a helper type to represent recursive "tree-like" variants - `recursive_wrapper<T>` - a helper type to represent recursive "tree-like" variants
- `apply_visitor(visitor, myVariant)` - to invoke a custom visitor on the variant's underlying type - `apply_visitor(visitor, myVariant)` - to invoke a custom visitor on the variant's underlying type
- `get<T>()` - a function to directly unwrap a variant's underlying type - `get<T>()` - a function to directly unwrap a variant's underlying type
- `.match([](Type){})` - a variant convenience member function taking an arbitrary number of lambdas creating a visitor behind the scenes and applying it to the variant - `.match([](Type){})` - a variant convenience member function taking an arbitrary number of lambdas creating a visitor behind the scenes and applying it to the variant
### Basic Usage - HTTP API Example ### Basic Usage - HTTP API Example
Suppose you want to represent a HTTP API response which is either a JSON result or an error: Suppose you want to represent a HTTP API response which is either a JSON result or an error:
@ -46,7 +46,7 @@ Response ret = makeRequest();
To see which type the `Response` holds you pattern match on the variant unwrapping the underlying value: To see which type the `Response` holds you pattern match on the variant unwrapping the underlying value:
```c++ ```c++
ret.match([] (Result r) { print(r.object); } ret.match([] (Result r) { print(r.object); },
[] (Error e) { print(e.message); }); [] (Error e) { print(e.message); });
``` ```
@ -69,12 +69,10 @@ apply_visitor(visitor, ret);
In both cases the compiler makes sure you handle all types the variant can represent at compile. In both cases the compiler makes sure you handle all types the variant can represent at compile.
### Recursive Variants - JSON Example ### Recursive Variants - JSON Example
[JSON](http://www.json.org/) consists of types `String`, `Number`, `True`, `False`, `Null`, `Array` and `Object`. [JSON](http://www.json.org/) consists of types `String`, `Number`, `True`, `False`, `Null`, `Array` and `Object`.
```c++ ```c++
struct String { string value; }; struct String { string value; };
struct Number { double value; }; struct Number { double value; };
@ -111,7 +109,7 @@ struct Object {
}; };
``` ```
For walkig the JSON representation you can again either create a `JSONVisitor`: For walking the JSON representation you can again either create a `JSONVisitor`:
```c++ ```c++
struct JSONVisitor { struct JSONVisitor {
@ -146,6 +144,7 @@ struct Node {
uint64_t value; uint64_t value;
} }
``` ```
### Advanced Usage Tips ### Advanced Usage Tips
Creating type aliases for variants is a great way to reduce repetition. Creating type aliases for variants is a great way to reduce repetition.
@ -164,7 +163,6 @@ struct APIResult : variant<Error, Result> {
} }
``` ```
## Why use Mapbox Variant? ## Why use Mapbox Variant?
Mapbox variant has the same speedy performance of `boost::variant` but is Mapbox variant has the same speedy performance of `boost::variant` but is
@ -180,7 +178,6 @@ Time to compile header | 185 ms | 675 ms
(Numbers from an older version of Mapbox variant.) (Numbers from an older version of Mapbox variant.)
## Goals ## Goals
Mapbox `variant` has been a very valuable, lightweight alternative for apps Mapbox `variant` has been a very valuable, lightweight alternative for apps
@ -206,7 +203,6 @@ Want to know more about the upcoming standard? Have a look at our
Most modern high-level languages provide ways to express sum types directly. Most modern high-level languages provide ways to express sum types directly.
If you're curious have a look at Haskell's pattern matching or Rust's and Swift's enums. If you're curious have a look at Haskell's pattern matching or Rust's and Swift's enums.
## Depends ## Depends
- Compiler supporting `-std=c++11` or `-std=c++14` - Compiler supporting `-std=c++11` or `-std=c++14`
@ -224,35 +220,29 @@ Tested with:
- clang++-3.9 - clang++-3.9
- Visual Studio 2015 - Visual Studio 2015
## Unit Tests ## Unit Tests
On Unix systems compile and run the unit tests with `make test`. On Unix systems compile and run the unit tests with `make test`.
On Windows run `scripts/build-local.bat`. On Windows run `scripts/build-local.bat`.
## Limitations ## Limitations
* The `variant` can not hold references (something like `variant<int&>` is - The `variant` can not hold references (something like `variant<int&>` is
not possible). You might want to try `std::reference_wrapper` instead. not possible). You might want to try `std::reference_wrapper` instead.
## Deprecations ## Deprecations
* The included implementation of `optional` is deprecated and will be removed - The included implementation of `optional` is deprecated and will be removed
in a future version. See https://github.com/mapbox/variant/issues/64. in a future version. See [issue #64](https://github.com/mapbox/variant/issues/64).
* Old versions of the code needed visitors to derive from `static_visitor`. - Old versions of the code needed visitors to derive from `static_visitor`.
This is not needed any more and marked as deprecated. The `static_visitor` This is not needed any more and marked as deprecated. The `static_visitor`
class will be removed in future versions. class will be removed in future versions.
## Benchmarks ## Benchmarks
make bench make bench
## Check object sizes ## Check object sizes
make sizes /path/to/boost/variant.hpp make sizes /path/to/boost/variant.hpp

View File

@ -11,6 +11,7 @@
#include <typeinfo> #include <typeinfo>
#include <utility> #include <utility>
#include <functional> #include <functional>
#include <limits>
#include <mapbox/recursive_wrapper.hpp> #include <mapbox/recursive_wrapper.hpp>
#include <mapbox/variant_visitor.hpp> #include <mapbox/variant_visitor.hpp>
@ -74,19 +75,19 @@ public:
}; // class bad_variant_access }; // class bad_variant_access
template <typename R = void> #if !defined(MAPBOX_VARIANT_MINIMIZE_SIZE)
struct MAPBOX_VARIANT_DEPRECATED static_visitor using type_index_t = unsigned int;
{ #else
using result_type = R; #if defined(MAPBOX_VARIANT_OPTIMIZE_FOR_SPEED)
using type_index_t = std::uint_fast8_t;
protected: #else
static_visitor() {} using type_index_t = std::uint_least8_t;
~static_visitor() {} #endif
}; #endif
namespace detail { namespace detail {
static constexpr std::size_t invalid_value = std::size_t(-1); static constexpr type_index_t invalid_value = type_index_t(-1);
template <typename T, typename... Types> template <typename T, typename... Types>
struct direct_type; struct direct_type;
@ -94,7 +95,7 @@ struct direct_type;
template <typename T, typename First, typename... Types> template <typename T, typename First, typename... Types>
struct direct_type<T, First, Types...> struct direct_type<T, First, Types...>
{ {
static constexpr std::size_t index = std::is_same<T, First>::value static constexpr type_index_t index = std::is_same<T, First>::value
? sizeof...(Types) ? sizeof...(Types)
: direct_type<T, Types...>::index; : direct_type<T, Types...>::index;
}; };
@ -102,15 +103,28 @@ struct direct_type<T, First, Types...>
template <typename T> template <typename T>
struct direct_type<T> struct direct_type<T>
{ {
static constexpr std::size_t index = invalid_value; static constexpr type_index_t index = invalid_value;
}; };
#if __cpp_lib_logical_traits >= 201510L #if __cpp_lib_logical_traits >= 201510L
using std::conjunction;
using std::disjunction; using std::disjunction;
#else #else
template <typename...>
struct conjunction : std::true_type {};
template <typename B1>
struct conjunction<B1> : B1 {};
template <typename B1, typename B2>
struct conjunction<B1, B2> : std::conditional<B1::value, B2, B1>::type {};
template <typename B1, typename... Bs>
struct conjunction<B1, Bs...> : std::conditional<B1::value, conjunction<Bs...>, B1>::type {};
template <typename...> template <typename...>
struct disjunction : std::false_type {}; struct disjunction : std::false_type {};
@ -131,7 +145,7 @@ struct convertible_type;
template <typename T, typename First, typename... Types> template <typename T, typename First, typename... Types>
struct convertible_type<T, First, Types...> struct convertible_type<T, First, Types...>
{ {
static constexpr std::size_t index = std::is_convertible<T, First>::value static constexpr type_index_t index = std::is_convertible<T, First>::value
? disjunction<std::is_convertible<T, Types>...>::value ? invalid_value : sizeof...(Types) ? disjunction<std::is_convertible<T, Types>...>::value ? invalid_value : sizeof...(Types)
: convertible_type<T, Types...>::index; : convertible_type<T, Types...>::index;
}; };
@ -139,64 +153,88 @@ struct convertible_type<T, First, Types...>
template <typename T> template <typename T>
struct convertible_type<T> struct convertible_type<T>
{ {
static constexpr std::size_t index = invalid_value; static constexpr type_index_t index = invalid_value;
}; };
template <typename T, typename... Types> template <typename T, typename... Types>
struct value_traits struct value_traits
{ {
using value_type = typename std::remove_const<typename std::remove_reference<T>::type>::type; using value_type = typename std::remove_const<typename std::remove_reference<T>::type>::type;
static constexpr std::size_t direct_index = direct_type<value_type, Types...>::index; using value_type_wrapper = recursive_wrapper<value_type>;
static constexpr type_index_t direct_index = direct_type<value_type, Types...>::index;
static constexpr bool is_direct = direct_index != invalid_value; static constexpr bool is_direct = direct_index != invalid_value;
static constexpr std::size_t index = is_direct ? direct_index : convertible_type<value_type, Types...>::index; static constexpr type_index_t index_direct_or_wrapper = is_direct ? direct_index : direct_type<value_type_wrapper, Types...>::index;
static constexpr bool is_direct_or_wrapper = index_direct_or_wrapper != invalid_value;
static constexpr type_index_t index = is_direct_or_wrapper ? index_direct_or_wrapper : convertible_type<value_type, Types...>::index;
static constexpr bool is_valid = index != invalid_value; static constexpr bool is_valid = index != invalid_value;
static constexpr std::size_t tindex = is_valid ? sizeof...(Types)-index : 0; static constexpr type_index_t tindex = is_valid ? sizeof...(Types)-index : 0;
using target_type = typename std::tuple_element<tindex, std::tuple<void, Types...>>::type; using target_type = typename std::tuple_element<tindex, std::tuple<void, Types...>>::type;
}; };
template <typename T, typename R = void> template <typename Src, typename Dest>
struct enable_if_type struct copy_cvref
{ {
using type = R; using type = Dest;
}; };
template <typename F, typename V, typename Enable = void> template <typename Src, typename Dest>
struct result_of_unary_visit struct copy_cvref<Src const&, Dest>
{ {
using type = typename std::result_of<F(V&)>::type; using type = Dest const&;
}; };
template <typename F, typename V> template <typename Src, typename Dest>
struct result_of_unary_visit<F, V, typename enable_if_type<typename F::result_type>::type> struct copy_cvref<Src&, Dest>
{ {
using type = typename F::result_type; using type = Dest&;
}; };
template <typename F, typename V, typename Enable = void> template <typename Src, typename Dest>
struct result_of_binary_visit struct copy_cvref<Src&&, Dest>
{ {
using type = typename std::result_of<F(V&, V&)>::type; using type = Dest&&;
}; };
template <typename F, typename V> template <typename F, typename = void>
struct result_of_binary_visit<F, V, typename enable_if_type<typename F::result_type>::type> struct deduced_result_type
{};
template <typename F, typename... Args>
struct deduced_result_type<F(Args...), decltype((void)std::declval<F>()(std::declval<Args>()...))>
{ {
using type = typename F::result_type; using type = decltype(std::declval<F>()(std::declval<Args>()...));
}; };
template <std::size_t arg1, std::size_t... others> template <typename F, typename = void>
struct visitor_result_type : deduced_result_type<F>
{};
// specialization for explicit result_type member in visitor class
template <typename F, typename... Args>
struct visitor_result_type<F(Args...), decltype((void)std::declval<typename std::decay<F>::type::result_type>())>
{
using type = typename std::decay<F>::type::result_type;
};
template <typename F, typename T>
using result_of_unary_visit = typename visitor_result_type<F&&(T&&)>::type;
template <typename F, typename T>
using result_of_binary_visit = typename visitor_result_type<F&&(T&&, T&&)>::type;
template <type_index_t arg1, type_index_t... others>
struct static_max; struct static_max;
template <std::size_t arg> template <type_index_t arg>
struct static_max<arg> struct static_max<arg>
{ {
static const std::size_t value = arg; static const type_index_t value = arg;
}; };
template <std::size_t arg1, std::size_t arg2, std::size_t... others> template <type_index_t arg1, type_index_t arg2, type_index_t... others>
struct static_max<arg1, arg2, others...> struct static_max<arg1, arg2, others...>
{ {
static const std::size_t value = arg1 >= arg2 ? static_max<arg1, others...>::value : static_max<arg2, others...>::value; static const type_index_t value = arg1 >= arg2 ? static_max<arg1, others...>::value : static_max<arg2, others...>::value;
}; };
template <typename... Types> template <typename... Types>
@ -205,7 +243,7 @@ struct variant_helper;
template <typename T, typename... Types> template <typename T, typename... Types>
struct variant_helper<T, Types...> struct variant_helper<T, Types...>
{ {
VARIANT_INLINE static void destroy(const std::size_t type_index, void* data) VARIANT_INLINE static void destroy(const type_index_t type_index, void* data)
{ {
if (type_index == sizeof...(Types)) if (type_index == sizeof...(Types))
{ {
@ -217,7 +255,7 @@ struct variant_helper<T, Types...>
} }
} }
VARIANT_INLINE static void move(const std::size_t old_type_index, void* old_value, void* new_value) VARIANT_INLINE static void move(const type_index_t old_type_index, void* old_value, void* new_value)
{ {
if (old_type_index == sizeof...(Types)) if (old_type_index == sizeof...(Types))
{ {
@ -229,7 +267,7 @@ struct variant_helper<T, Types...>
} }
} }
VARIANT_INLINE static void copy(const std::size_t old_type_index, const void* old_value, void* new_value) VARIANT_INLINE static void copy(const type_index_t old_type_index, const void* old_value, void* new_value)
{ {
if (old_type_index == sizeof...(Types)) if (old_type_index == sizeof...(Types))
{ {
@ -245,253 +283,182 @@ struct variant_helper<T, Types...>
template <> template <>
struct variant_helper<> struct variant_helper<>
{ {
VARIANT_INLINE static void destroy(const std::size_t, void*) {} VARIANT_INLINE static void destroy(const type_index_t, void*) {}
VARIANT_INLINE static void move(const std::size_t, void*, void*) {} VARIANT_INLINE static void move(const type_index_t, void*, void*) {}
VARIANT_INLINE static void copy(const std::size_t, const void*, void*) {} VARIANT_INLINE static void copy(const type_index_t, const void*, void*) {}
}; };
template <typename T> template <typename T>
struct unwrapper struct unwrapper
{ {
static T const& apply_const(T const& obj) { return obj; } using value_type = T;
static T& apply(T& obj) { return obj; }
};
template <typename T> template <typename V>
struct unwrapper<recursive_wrapper<T>> static auto apply(typename std::remove_reference<V>::type& var)
-> typename std::enable_if<std::is_lvalue_reference<V>::value,
decltype(var.template get_unchecked<T>())>::type
{ {
static auto apply_const(recursive_wrapper<T> const& obj) return var.template get_unchecked<T>();
-> typename recursive_wrapper<T>::type const&
{
return obj.get();
} }
static auto apply(recursive_wrapper<T>& obj)
-> typename recursive_wrapper<T>::type& template <typename V>
static auto apply(typename std::remove_reference<V>::type& var)
-> typename std::enable_if<!std::is_lvalue_reference<V>::value,
decltype(std::move(var.template get_unchecked<T>()))>::type
{ {
return obj.get(); return std::move(var.template get_unchecked<T>());
} }
}; };
template <typename T> template <typename T>
struct unwrapper<std::reference_wrapper<T>> struct unwrapper<recursive_wrapper<T>> : unwrapper<T>
{ {};
static auto apply_const(std::reference_wrapper<T> const& obj)
-> typename std::reference_wrapper<T>::type const&
{
return obj.get();
}
static auto apply(std::reference_wrapper<T>& obj)
-> typename std::reference_wrapper<T>::type&
{
return obj.get();
}
};
template <typename F, typename V, typename R, typename... Types> template <typename T>
struct unwrapper<std::reference_wrapper<T>> : unwrapper<T>
{};
template <typename R, typename... Types>
struct dispatcher; struct dispatcher;
template <typename F, typename V, typename R, typename T, typename... Types> template <typename R, typename T, typename... Types>
struct dispatcher<F, V, R, T, Types...> struct dispatcher<R, T, Types...>
{ {
VARIANT_INLINE static R apply_const(V const& v, F&& f) template <typename V, typename F>
VARIANT_INLINE static R apply(V&& v, F&& f)
{ {
if (v.template is<T>()) if (v.template is<T>())
{ {
return f(unwrapper<T>::apply_const(v.template get_unchecked<T>())); return std::forward<F>(f)(unwrapper<T>::template apply<V>(v));
} }
else else
{ {
return dispatcher<F, V, R, Types...>::apply_const(v, std::forward<F>(f)); return dispatcher<R, Types...>::apply(std::forward<V>(v), std::forward<F>(f));
}
}
VARIANT_INLINE static R apply(V& v, F&& f)
{
if (v.template is<T>())
{
return f(unwrapper<T>::apply(v.template get_unchecked<T>()));
}
else
{
return dispatcher<F, V, R, Types...>::apply(v, std::forward<F>(f));
} }
} }
}; };
template <typename F, typename V, typename R, typename T> template <typename R, typename T>
struct dispatcher<F, V, R, T> struct dispatcher<R, T>
{ {
VARIANT_INLINE static R apply_const(V const& v, F&& f) template <typename V, typename F>
VARIANT_INLINE static R apply(V&& v, F&& f)
{ {
return f(unwrapper<T>::apply_const(v.template get_unchecked<T>())); return std::forward<F>(f)(unwrapper<T>::template apply<V>(v));
}
VARIANT_INLINE static R apply(V& v, F&& f)
{
return f(unwrapper<T>::apply(v.template get_unchecked<T>()));
} }
}; };
template <typename F, typename V, typename R, typename T, typename... Types> template <typename R, typename T, typename... Types>
struct binary_dispatcher_rhs; struct binary_dispatcher_rhs;
template <typename F, typename V, typename R, typename T0, typename T1, typename... Types> template <typename R, typename T0, typename T1, typename... Types>
struct binary_dispatcher_rhs<F, V, R, T0, T1, Types...> struct binary_dispatcher_rhs<R, T0, T1, Types...>
{ {
VARIANT_INLINE static R apply_const(V const& lhs, V const& rhs, F&& f) template <typename V, typename F>
VARIANT_INLINE static R apply(V&& lhs, V&& rhs, F&& f)
{ {
if (rhs.template is<T1>()) // call binary functor if (rhs.template is<T1>()) // call binary functor
{ {
return f(unwrapper<T0>::apply_const(lhs.template get_unchecked<T0>()), return std::forward<F>(f)(unwrapper<T0>::template apply<V>(lhs),
unwrapper<T1>::apply_const(rhs.template get_unchecked<T1>())); unwrapper<T1>::template apply<V>(rhs));
} }
else else
{ {
return binary_dispatcher_rhs<F, V, R, T0, Types...>::apply_const(lhs, rhs, std::forward<F>(f)); return binary_dispatcher_rhs<R, T0, Types...>::apply(std::forward<V>(lhs),
} std::forward<V>(rhs),
} std::forward<F>(f));
VARIANT_INLINE static R apply(V& lhs, V& rhs, F&& f)
{
if (rhs.template is<T1>()) // call binary functor
{
return f(unwrapper<T0>::apply(lhs.template get_unchecked<T0>()),
unwrapper<T1>::apply(rhs.template get_unchecked<T1>()));
}
else
{
return binary_dispatcher_rhs<F, V, R, T0, Types...>::apply(lhs, rhs, std::forward<F>(f));
} }
} }
}; };
template <typename F, typename V, typename R, typename T0, typename T1> template <typename R, typename T0, typename T1>
struct binary_dispatcher_rhs<F, V, R, T0, T1> struct binary_dispatcher_rhs<R, T0, T1>
{ {
VARIANT_INLINE static R apply_const(V const& lhs, V const& rhs, F&& f) template <typename V, typename F>
VARIANT_INLINE static R apply(V&& lhs, V&& rhs, F&& f)
{ {
return f(unwrapper<T0>::apply_const(lhs.template get_unchecked<T0>()), return std::forward<F>(f)(unwrapper<T0>::template apply<V>(lhs),
unwrapper<T1>::apply_const(rhs.template get_unchecked<T1>())); unwrapper<T1>::template apply<V>(rhs));
}
VARIANT_INLINE static R apply(V& lhs, V& rhs, F&& f)
{
return f(unwrapper<T0>::apply(lhs.template get_unchecked<T0>()),
unwrapper<T1>::apply(rhs.template get_unchecked<T1>()));
} }
}; };
template <typename F, typename V, typename R, typename T, typename... Types> template <typename R, typename T, typename... Types>
struct binary_dispatcher_lhs; struct binary_dispatcher_lhs;
template <typename F, typename V, typename R, typename T0, typename T1, typename... Types> template <typename R, typename T0, typename T1, typename... Types>
struct binary_dispatcher_lhs<F, V, R, T0, T1, Types...> struct binary_dispatcher_lhs<R, T0, T1, Types...>
{ {
VARIANT_INLINE static R apply_const(V const& lhs, V const& rhs, F&& f) template <typename V, typename F>
VARIANT_INLINE static R apply(V&& lhs, V&& rhs, F&& f)
{ {
if (lhs.template is<T1>()) // call binary functor if (lhs.template is<T1>()) // call binary functor
{ {
return f(unwrapper<T1>::apply_const(lhs.template get_unchecked<T1>()), return std::forward<F>(f)(unwrapper<T1>::template apply<V>(lhs),
unwrapper<T0>::apply_const(rhs.template get_unchecked<T0>())); unwrapper<T0>::template apply<V>(rhs));
} }
else else
{ {
return binary_dispatcher_lhs<F, V, R, T0, Types...>::apply_const(lhs, rhs, std::forward<F>(f)); return binary_dispatcher_lhs<R, T0, Types...>::apply(std::forward<V>(lhs),
} std::forward<V>(rhs),
} std::forward<F>(f));
VARIANT_INLINE static R apply(V& lhs, V& rhs, F&& f)
{
if (lhs.template is<T1>()) // call binary functor
{
return f(unwrapper<T1>::apply(lhs.template get_unchecked<T1>()),
unwrapper<T0>::apply(rhs.template get_unchecked<T0>()));
}
else
{
return binary_dispatcher_lhs<F, V, R, T0, Types...>::apply(lhs, rhs, std::forward<F>(f));
} }
} }
}; };
template <typename F, typename V, typename R, typename T0, typename T1> template <typename R, typename T0, typename T1>
struct binary_dispatcher_lhs<F, V, R, T0, T1> struct binary_dispatcher_lhs<R, T0, T1>
{ {
VARIANT_INLINE static R apply_const(V const& lhs, V const& rhs, F&& f) template <typename V, typename F>
VARIANT_INLINE static R apply(V&& lhs, V&& rhs, F&& f)
{ {
return f(unwrapper<T1>::apply_const(lhs.template get_unchecked<T1>()), return std::forward<F>(f)(unwrapper<T1>::template apply<V>(lhs),
unwrapper<T0>::apply_const(rhs.template get_unchecked<T0>())); unwrapper<T0>::template apply<V>(rhs));
}
VARIANT_INLINE static R apply(V& lhs, V& rhs, F&& f)
{
return f(unwrapper<T1>::apply(lhs.template get_unchecked<T1>()),
unwrapper<T0>::apply(rhs.template get_unchecked<T0>()));
} }
}; };
template <typename F, typename V, typename R, typename... Types> template <typename R, typename... Types>
struct binary_dispatcher; struct binary_dispatcher;
template <typename F, typename V, typename R, typename T, typename... Types> template <typename R, typename T, typename... Types>
struct binary_dispatcher<F, V, R, T, Types...> struct binary_dispatcher<R, T, Types...>
{ {
VARIANT_INLINE static R apply_const(V const& v0, V const& v1, F&& f) template <typename V, typename F>
VARIANT_INLINE static R apply(V&& v0, V&& v1, F&& f)
{ {
if (v0.template is<T>()) if (v0.template is<T>())
{ {
if (v1.template is<T>()) if (v1.template is<T>())
{ {
return f(unwrapper<T>::apply_const(v0.template get_unchecked<T>()), return std::forward<F>(f)(unwrapper<T>::template apply<V>(v0),
unwrapper<T>::apply_const(v1.template get_unchecked<T>())); // call binary functor unwrapper<T>::template apply<V>(v1)); // call binary functor
} }
else else
{ {
return binary_dispatcher_rhs<F, V, R, T, Types...>::apply_const(v0, v1, std::forward<F>(f)); return binary_dispatcher_rhs<R, T, Types...>::apply(std::forward<V>(v0),
std::forward<V>(v1),
std::forward<F>(f));
} }
} }
else if (v1.template is<T>()) else if (v1.template is<T>())
{ {
return binary_dispatcher_lhs<F, V, R, T, Types...>::apply_const(v0, v1, std::forward<F>(f)); return binary_dispatcher_lhs<R, T, Types...>::apply(std::forward<V>(v0),
std::forward<V>(v1),
std::forward<F>(f));
} }
return binary_dispatcher<F, V, R, Types...>::apply_const(v0, v1, std::forward<F>(f)); return binary_dispatcher<R, Types...>::apply(std::forward<V>(v0),
} std::forward<V>(v1),
std::forward<F>(f));
VARIANT_INLINE static R apply(V& v0, V& v1, F&& f)
{
if (v0.template is<T>())
{
if (v1.template is<T>())
{
return f(unwrapper<T>::apply(v0.template get_unchecked<T>()),
unwrapper<T>::apply(v1.template get_unchecked<T>())); // call binary functor
}
else
{
return binary_dispatcher_rhs<F, V, R, T, Types...>::apply(v0, v1, std::forward<F>(f));
}
}
else if (v1.template is<T>())
{
return binary_dispatcher_lhs<F, V, R, T, Types...>::apply(v0, v1, std::forward<F>(f));
}
return binary_dispatcher<F, V, R, Types...>::apply(v0, v1, std::forward<F>(f));
} }
}; };
template <typename F, typename V, typename R, typename T> template <typename R, typename T>
struct binary_dispatcher<F, V, R, T> struct binary_dispatcher<R, T>
{ {
VARIANT_INLINE static R apply_const(V const& v0, V const& v1, F&& f) template <typename V, typename F>
VARIANT_INLINE static R apply(V&& v0, V&& v1, F&& f)
{ {
return f(unwrapper<T>::apply_const(v0.template get_unchecked<T>()), return std::forward<F>(f)(unwrapper<T>::template apply<V>(v0),
unwrapper<T>::apply_const(v1.template get_unchecked<T>())); // call binary functor unwrapper<T>::template apply<V>(v1)); // call binary functor
}
VARIANT_INLINE static R apply(V& v0, V& v1, F&& f)
{
return f(unwrapper<T>::apply(v0.template get_unchecked<T>()),
unwrapper<T>::apply(v1.template get_unchecked<T>())); // call binary functor
} }
}; };
@ -545,16 +512,15 @@ struct hasher
} // namespace detail } // namespace detail
struct no_init struct no_init {};
{
};
template <typename... Types> template <typename... Types>
class variant class variant
{ {
static_assert(sizeof...(Types) > 0, "Template parameter type list of variant can not be empty"); static_assert(sizeof...(Types) > 0, "Template parameter type list of variant can not be empty.");
static_assert(!detail::disjunction<std::is_reference<Types>...>::value, "Variant can not hold reference types. Maybe use std::reference_wrapper?"); static_assert(!detail::disjunction<std::is_reference<Types>...>::value, "Variant can not hold reference types. Maybe use std::reference_wrapper?");
static_assert(!detail::disjunction<std::is_array<Types>...>::value, "Variant can not hold array types.");
static_assert(sizeof...(Types) < std::numeric_limits<type_index_t>::max(), "Internal index type must be able to accommodate all alternatives.");
private: private:
static const std::size_t data_size = detail::static_max<sizeof(Types)...>::value; static const std::size_t data_size = detail::static_max<sizeof(Types)...>::value;
static const std::size_t data_align = detail::static_max<alignof(Types)...>::value; static const std::size_t data_align = detail::static_max<alignof(Types)...>::value;
@ -563,17 +529,25 @@ public:
using types = std::tuple<Types...>; using types = std::tuple<Types...>;
private: private:
using first_type = typename std::tuple_element<0, types>::type; using first_type = typename std::tuple_element<0, types>::type;
using unwrap_first_type = typename detail::unwrapper<first_type>::value_type;
using data_type = typename std::aligned_storage<data_size, data_align>::type; using data_type = typename std::aligned_storage<data_size, data_align>::type;
using helper_type = detail::variant_helper<Types...>; using helper_type = detail::variant_helper<Types...>;
std::size_t type_index; template <typename V, typename T = unwrap_first_type>
using alternative_ref = typename detail::copy_cvref<V, T>::type;
type_index_t type_index;
#ifdef __clang_analyzer__
data_type data {};
#else
data_type data; data_type data;
#endif
public: public:
VARIANT_INLINE variant() noexcept(std::is_nothrow_default_constructible<first_type>::value) VARIANT_INLINE variant() noexcept(std::is_nothrow_default_constructible<first_type>::value)
: type_index(sizeof...(Types)-1) : type_index(sizeof...(Types)-1)
{ {
static_assert(std::is_default_constructible<first_type>::value, "First type in variant must be default constructible to allow default construction of variant"); static_assert(std::is_default_constructible<first_type>::value, "First type in variant must be default constructible to allow default construction of variant.");
new (&data) first_type(); new (&data) first_type();
} }
@ -595,7 +569,8 @@ public:
helper_type::copy(old.type_index, &old.data, &data); helper_type::copy(old.type_index, &old.data, &data);
} }
VARIANT_INLINE variant(variant<Types...>&& old) noexcept(std::is_nothrow_move_constructible<types>::value) VARIANT_INLINE variant(variant<Types...>&& old)
noexcept(detail::conjunction<std::is_nothrow_move_constructible<Types>...>::value)
: type_index(old.type_index) : type_index(old.type_index)
{ {
helper_type::move(old.type_index, &old.data, &data); helper_type::move(old.type_index, &old.data, &data);
@ -620,21 +595,34 @@ private:
public: public:
VARIANT_INLINE variant<Types...>& operator=(variant<Types...>&& other) VARIANT_INLINE variant<Types...>& operator=(variant<Types...>&& other)
// note we check for nothrow-constructible, not nothrow-assignable, since
// move_assign uses move-construction via placement new.
noexcept(detail::conjunction<std::is_nothrow_move_constructible<Types>...>::value)
{ {
if (this == &other) { // playing safe in release mode, hit assertion in debug.
assert(false);
return *this;
}
move_assign(std::move(other)); move_assign(std::move(other));
return *this; return *this;
} }
VARIANT_INLINE variant<Types...>& operator=(variant<Types...> const& other) VARIANT_INLINE variant<Types...>& operator=(variant<Types...> const& other)
{ {
if (this != &other)
copy_assign(other); copy_assign(other);
return *this; return *this;
} }
// conversions // conversions
// move-assign // move-assign
template <typename T> template <typename T, typename Traits = detail::value_traits<T, Types...>,
VARIANT_INLINE variant<Types...>& operator=(T&& rhs) noexcept typename Enable = typename std::enable_if<Traits::is_valid && !std::is_same<variant<Types...>, typename Traits::value_type>::value>::type >
VARIANT_INLINE variant<Types...>& operator=(T&& rhs)
// not that we check is_nothrow_constructible<T>, not is_nothrow_move_assignable<T>,
// since we construct a temporary
noexcept(std::is_nothrow_constructible<typename Traits::target_type, T&&>::value
&& std::is_nothrow_move_assignable<variant<Types...>>::value)
{ {
variant<Types...> temp(std::forward<T>(rhs)); variant<Types...> temp(std::forward<T>(rhs));
move_assign(std::move(temp)); move_assign(std::move(temp));
@ -824,7 +812,7 @@ public:
// This function is deprecated because it returns an internal index field. // This function is deprecated because it returns an internal index field.
// Use which() instead. // Use which() instead.
MAPBOX_VARIANT_DEPRECATED VARIANT_INLINE std::size_t get_type_index() const MAPBOX_VARIANT_DEPRECATED VARIANT_INLINE type_index_t get_type_index() const
{ {
return type_index; return type_index;
} }
@ -843,51 +831,44 @@ public:
// visitor // visitor
// unary // unary
template <typename F, typename V, typename R = typename detail::result_of_unary_visit<F, first_type>::type> template <typename F, typename V, typename T0 = alternative_ref<V>,
auto VARIANT_INLINE static visit(V const& v, F&& f) typename R = detail::result_of_unary_visit<F, T0>>
-> decltype(detail::dispatcher<F, V, R, Types...>::apply_const(v, std::forward<F>(f))) VARIANT_INLINE static R visit(V&& v, F&& f)
{ {
return detail::dispatcher<F, V, R, Types...>::apply_const(v, std::forward<F>(f)); return detail::dispatcher<R, Types...>::apply(std::forward<V>(v), std::forward<F>(f));
}
// non-const
template <typename F, typename V, typename R = typename detail::result_of_unary_visit<F, first_type>::type>
auto VARIANT_INLINE static visit(V& v, F&& f)
-> decltype(detail::dispatcher<F, V, R, Types...>::apply(v, std::forward<F>(f)))
{
return detail::dispatcher<F, V, R, Types...>::apply(v, std::forward<F>(f));
} }
// binary // binary
// const template <typename F, typename V, typename T0 = alternative_ref<V>,
template <typename F, typename V, typename R = typename detail::result_of_binary_visit<F, first_type>::type> typename R = detail::result_of_binary_visit<F, T0>>
auto VARIANT_INLINE static binary_visit(V const& v0, V const& v1, F&& f) VARIANT_INLINE static R binary_visit(V&& v0, V&& v1, F&& f)
-> decltype(detail::binary_dispatcher<F, V, R, Types...>::apply_const(v0, v1, std::forward<F>(f)))
{ {
return detail::binary_dispatcher<F, V, R, Types...>::apply_const(v0, v1, std::forward<F>(f)); return detail::binary_dispatcher<R, Types...>::apply(std::forward<V>(v0),
} std::forward<V>(v1),
// non-const std::forward<F>(f));
template <typename F, typename V, typename R = typename detail::result_of_binary_visit<F, first_type>::type>
auto VARIANT_INLINE static binary_visit(V& v0, V& v1, F&& f)
-> decltype(detail::binary_dispatcher<F, V, R, Types...>::apply(v0, v1, std::forward<F>(f)))
{
return detail::binary_dispatcher<F, V, R, Types...>::apply(v0, v1, std::forward<F>(f));
} }
// match // match
// unary // unary
template <typename... Fs> template <typename... Fs>
auto VARIANT_INLINE match(Fs&&... fs) const auto VARIANT_INLINE match(Fs&&... fs) const&
-> decltype(variant::visit(*this, ::mapbox::util::make_visitor(std::forward<Fs>(fs)...))) -> decltype(variant::visit(*this, ::mapbox::util::make_visitor(std::forward<Fs>(fs)...)))
{ {
return variant::visit(*this, ::mapbox::util::make_visitor(std::forward<Fs>(fs)...)); return variant::visit(*this, ::mapbox::util::make_visitor(std::forward<Fs>(fs)...));
} }
// non-const // non-const
template <typename... Fs> template <typename... Fs>
auto VARIANT_INLINE match(Fs&&... fs) auto VARIANT_INLINE match(Fs&&... fs) &
-> decltype(variant::visit(*this, ::mapbox::util::make_visitor(std::forward<Fs>(fs)...))) -> decltype(variant::visit(*this, ::mapbox::util::make_visitor(std::forward<Fs>(fs)...)))
{ {
return variant::visit(*this, ::mapbox::util::make_visitor(std::forward<Fs>(fs)...)); return variant::visit(*this, ::mapbox::util::make_visitor(std::forward<Fs>(fs)...));
} }
template <typename... Fs>
auto VARIANT_INLINE match(Fs&&... fs) &&
-> decltype(variant::visit(std::move(*this), ::mapbox::util::make_visitor(std::forward<Fs>(fs)...)))
{
return variant::visit(std::move(*this), ::mapbox::util::make_visitor(std::forward<Fs>(fs)...));
}
~variant() noexcept // no-throw destructor ~variant() noexcept // no-throw destructor
{ {
@ -938,33 +919,19 @@ public:
}; };
// unary visitor interface // unary visitor interface
// const
template <typename F, typename V> template <typename F, typename V>
auto VARIANT_INLINE apply_visitor(F&& f, V const& v) -> decltype(V::visit(v, std::forward<F>(f))) auto VARIANT_INLINE apply_visitor(F&& f, V&& v)
-> decltype(v.visit(std::forward<V>(v), std::forward<F>(f)))
{ {
return V::visit(v, std::forward<F>(f)); return v.visit(std::forward<V>(v), std::forward<F>(f));
}
// non-const
template <typename F, typename V>
auto VARIANT_INLINE apply_visitor(F&& f, V& v) -> decltype(V::visit(v, std::forward<F>(f)))
{
return V::visit(v, std::forward<F>(f));
} }
// binary visitor interface // binary visitor interface
// const
template <typename F, typename V> template <typename F, typename V>
auto VARIANT_INLINE apply_visitor(F&& f, V const& v0, V const& v1) -> decltype(V::binary_visit(v0, v1, std::forward<F>(f))) auto VARIANT_INLINE apply_visitor(F&& f, V&& v0, V&& v1)
-> decltype(v0.binary_visit(std::forward<V>(v0), std::forward<V>(v1), std::forward<F>(f)))
{ {
return V::binary_visit(v0, v1, std::forward<F>(f)); return v0.binary_visit(std::forward<V>(v0), std::forward<V>(v1), std::forward<F>(f));
}
// non-const
template <typename F, typename V>
auto VARIANT_INLINE apply_visitor(F&& f, V& v0, V& v1) -> decltype(V::binary_visit(v0, v1, std::forward<F>(f)))
{
return V::binary_visit(v0, v1, std::forward<F>(f));
} }
// getter interface // getter interface
@ -996,6 +963,78 @@ ResultType const& get_unchecked(T const& var)
{ {
return var.template get_unchecked<ResultType>(); return var.template get_unchecked<ResultType>();
} }
// variant_size
template <typename T>
struct variant_size;
//variable templates is c++14
//template <typename T>
//constexpr std::size_t variant_size_v = variant_size<T>::value;
template <typename T>
struct variant_size<const T>
: variant_size<T> {};
template <typename T>
struct variant_size<volatile T>
: variant_size<T> {};
template <typename T>
struct variant_size<const volatile T>
: variant_size<T> {};
template <typename... Types>
struct variant_size<variant<Types...>>
: std::integral_constant<std::size_t, sizeof...(Types)> {};
// variant_alternative
template <std::size_t Index, typename T>
struct variant_alternative;
#if defined(__clang__)
#if __has_builtin(__type_pack_element)
#define has_type_pack_element
#endif
#endif
#if defined(has_type_pack_element)
template <std::size_t Index, typename ...Types>
struct variant_alternative<Index, variant<Types...>>
{
static_assert(sizeof...(Types) > Index , "Index out of range");
using type = __type_pack_element<Index, Types...>;
};
#else
template <std::size_t Index, typename First, typename...Types>
struct variant_alternative<Index, variant<First, Types...>>
: variant_alternative<Index - 1, variant<Types...>>
{
static_assert(sizeof...(Types) > Index -1 , "Index out of range");
};
template <typename First, typename...Types>
struct variant_alternative<0, variant<First, Types...>>
{
using type = First;
};
#endif
template <size_t Index, typename T>
using variant_alternative_t = typename variant_alternative<Index, T>::type;
template <size_t Index, typename T>
struct variant_alternative<Index, const T>
: std::add_const<variant_alternative<Index, T>> {};
template <size_t Index, typename T>
struct variant_alternative<Index, volatile T>
: std::add_volatile<variant_alternative<Index, T>> {};
template <size_t Index, typename T>
struct variant_alternative<Index, const volatile T>
: std::add_cv<variant_alternative<Index, T>> {};
} // namespace util } // namespace util
} // namespace mapbox } // namespace mapbox
@ -1008,6 +1047,7 @@ struct hash< ::mapbox::util::variant<Types...>> {
return ::mapbox::util::apply_visitor(::mapbox::util::detail::hasher{}, v); return ::mapbox::util::apply_visitor(::mapbox::util::detail::hasher{}, v);
} }
}; };
} }
#endif // MAPBOX_UTIL_VARIANT_HPP #endif // MAPBOX_UTIL_VARIANT_HPP

View File

@ -0,0 +1,85 @@
#ifndef VARIANT_CAST_HPP
#define VARIANT_CAST_HPP
#include <type_traits>
namespace mapbox {
namespace util {
namespace detail {
template <class T>
class static_caster
{
public:
template <class V>
T& operator()(V& v) const
{
return static_cast<T&>(v);
}
};
template <class T>
class dynamic_caster
{
public:
using result_type = T&;
template <class V>
T& operator()(V& v, typename std::enable_if<!std::is_polymorphic<V>::value>::type* = nullptr) const
{
throw std::bad_cast();
}
template <class V>
T& operator()(V& v, typename std::enable_if<std::is_polymorphic<V>::value>::type* = nullptr) const
{
return dynamic_cast<T&>(v);
}
};
template <class T>
class dynamic_caster<T*>
{
public:
using result_type = T*;
template <class V>
T* operator()(V& v, typename std::enable_if<!std::is_polymorphic<V>::value>::type* = nullptr) const
{
return nullptr;
}
template <class V>
T* operator()(V& v, typename std::enable_if<std::is_polymorphic<V>::value>::type* = nullptr) const
{
return dynamic_cast<T*>(&v);
}
};
}
template <class T, class V>
typename detail::dynamic_caster<T>::result_type
dynamic_variant_cast(V& v)
{
return mapbox::util::apply_visitor(detail::dynamic_caster<T>(), v);
}
template <class T, class V>
typename detail::dynamic_caster<const T>::result_type
dynamic_variant_cast(const V& v)
{
return mapbox::util::apply_visitor(detail::dynamic_caster<const T>(), v);
}
template <class T, class V>
T& static_variant_cast(V& v)
{
return mapbox::util::apply_visitor(detail::static_caster<T>(), v);
}
template <class T, class V>
const T& static_variant_cast(const V& v)
{
return mapbox::util::apply_visitor(detail::static_caster<const T>(), v);
}
}
}
#endif // VARIANT_CAST_HPP

View File

@ -1,6 +1,8 @@
#ifndef MAPBOX_UTIL_VARIANT_VISITOR_HPP #ifndef MAPBOX_UTIL_VARIANT_VISITOR_HPP
#define MAPBOX_UTIL_VARIANT_VISITOR_HPP #define MAPBOX_UTIL_VARIANT_VISITOR_HPP
#include <utility>
namespace mapbox { namespace mapbox {
namespace util { namespace util {
@ -10,26 +12,29 @@ struct visitor;
template <typename Fn> template <typename Fn>
struct visitor<Fn> : Fn struct visitor<Fn> : Fn
{ {
using type = Fn;
using Fn::operator(); using Fn::operator();
visitor(Fn fn) : Fn(fn) {} template<typename T>
visitor(T&& fn) : Fn(std::forward<T>(fn)) {}
}; };
template <typename Fn, typename... Fns> template <typename Fn, typename... Fns>
struct visitor<Fn, Fns...> : Fn, visitor<Fns...> struct visitor<Fn, Fns...> : Fn, visitor<Fns...>
{ {
using type = visitor;
using Fn::operator(); using Fn::operator();
using visitor<Fns...>::operator(); using visitor<Fns...>::operator();
visitor(Fn fn, Fns... fns) : Fn(fn), visitor<Fns...>(fns...) {} template<typename T, typename... Ts>
visitor(T&& fn, Ts&&... fns)
: Fn(std::forward<T>(fn))
, visitor<Fns...>(std::forward<Ts>(fns)...) {}
}; };
template <typename... Fns> template <typename... Fns>
visitor<Fns...> make_visitor(Fns... fns) visitor<typename std::decay<Fns>::type...> make_visitor(Fns&&... fns)
{ {
return visitor<Fns...>(fns...); return visitor<typename std::decay<Fns>::type...>
(std::forward<Fns>(fns)...);
} }
} // namespace util } // namespace util

10
third_party/variant/package.json vendored Normal file
View File

@ -0,0 +1,10 @@
{
"name": "variant",
"version": "1.1.6",
"description": "C++11/C++14 variant",
"main": "./package.json",
"repository" : {
"type" : "git",
"url" : "git://github.com/mapbox/variant.git"
}
}

View File

@ -1,4 +1,4 @@
// @EXPECTED: enable_if // @EXPECTED: no matching .*\<function for call to .*\<get\>
#include <mapbox/variant.hpp> #include <mapbox/variant.hpp>

View File

@ -1,4 +1,4 @@
// @EXPECTED: const int // @EXPECTED: no matching function for call to .*\<apply_visitor\>
#include <mapbox/variant.hpp> #include <mapbox/variant.hpp>

File diff suppressed because it is too large Load Diff

View File

@ -10,6 +10,15 @@
using namespace mapbox::util; using namespace mapbox::util;
template <typename T>
struct tag
{
static void dump(const char* prefix)
{
std::cout << prefix << ": " << typeid(tag<T>).name() << std::endl;
}
};
template <typename Left, typename Right> template <typename Left, typename Right>
using Either = mapbox::util::variant<Left, Right>; using Either = mapbox::util::variant<Left, Right>;
@ -55,6 +64,37 @@ void test_singleton_variant()
apply_visitor(make_visitor([](int) {}), singleton); apply_visitor(make_visitor([](int) {}), singleton);
} }
// See #180
struct test_call_nonconst_member_visitor
{
template <typename T>
void operator() (T & obj) const
{
tag<decltype(obj)>::dump("test_call_nonconst_member: visitor");
obj.foo();
}
};
void test_call_nonconst_member()
{
struct object
{
void foo() { val = 42;}
int val = 0;
};
variant<object> v = object{};
apply_visitor(test_call_nonconst_member_visitor{}, v);
#ifdef HAS_CPP14_SUPPORT
apply_visitor([](auto& obj)
{
tag<decltype(obj)>::dump("test_call_nonconst_member: lambda");
obj.foo();
}, v);
#endif
}
void test_lambda_overloads_sfinae() void test_lambda_overloads_sfinae()
#ifdef HAS_CPP14_SUPPORT #ifdef HAS_CPP14_SUPPORT
{ {
@ -85,6 +125,9 @@ void test_match_singleton()
{ {
variant<int> singleton = 5; variant<int> singleton = 5;
singleton.match([](int) {}); singleton.match([](int) {});
auto lambda = [](int) {};
singleton.match(lambda);
} }
void test_match_overloads() void test_match_overloads()
@ -112,16 +155,128 @@ void test_match_overloads_capture()
std::cout << "Got " << ok << " ok, " << err << " err" << std::endl; std::cout << "Got " << ok << " ok, " << err << " err" << std::endl;
} }
struct MovableOnly
{
MovableOnly() = default;
MovableOnly(MovableOnly&&) = default;
MovableOnly& operator=(MovableOnly&&) = default;
};
struct MovableCopyable
{
MovableCopyable() = default;
MovableCopyable(MovableCopyable&&) = default;
MovableCopyable& operator=(MovableCopyable&&) = default;
MovableCopyable(const MovableCopyable&) = default;
MovableCopyable& operator=(const MovableCopyable&) = default;
};
void test_match_overloads_init_capture()
#ifdef HAS_CPP14_SUPPORT
{
Either<Error, Response> rv;
rv = Error{};
rv.match([p = MovableOnly{}](auto&&) {});
{
auto lambda = [p = MovableCopyable{}](auto&&) {};
rv.match(lambda);
rv.match([p = MovableOnly{}](Response) { std::cout << "Response\n"; },
[p = MovableOnly{}](Error) { std::cout << "Error\n"; });
}
{
auto lambda = [](Error) { std::cout << "Error\n"; };
rv.match([p = MovableOnly{}](Response) { std::cout << "Response\n"; },
lambda);
rv.match(lambda,
[p = MovableOnly{}](Response) { std::cout << "Response\n"; });
}
}
#else
{
}
#endif
// See #140
void test_match_overloads_otherwise()
#ifdef HAS_CPP14_SUPPORT
{
struct Center
{
};
struct Indent
{
};
struct Justify
{
};
struct None
{
};
using Properties = mapbox::util::variant<Center, Indent, Justify, None>;
Properties props = Justify{};
props.match([&](Center) { std::cout << "Center\n"; }, //
[&](Indent) { std::cout << "Indent\n"; }, //
[&](auto&&) { std::cout << "Otherwise\n"; }); //
}
#else
{
}
#endif
template <typename>
struct Moveable
{
Moveable() = default; // Default constructible
Moveable(const Moveable&) = delete; // Disable copy ctor
Moveable& operator=(const Moveable&) = delete; // Disable copy assign op
Moveable(Moveable&&) = default; // Enable move ctor
Moveable& operator=(Moveable&&) = default; // Enable move assign op
};
void test_match_move_out_of_variant()
{
// Distinguishable at type level
using T1 = Moveable<struct Tag1>;
using T2 = Moveable<struct Tag2>;
using T3 = mapbox::util::recursive_wrapper<int>;
mapbox::util::variant<T1, T2> v = T1{};
std::move(v).match([](T1&&) {}, // Consume T1 by value
[](T2&&) {}); // Consume T2 by value
mapbox::util::variant<T3, T2> w = T2{};
std::move(w).match([](int&&) {}, // Consume unwrapped int
[](T2&&) {}); // Consume T2 by value
}
int main() int main()
{ {
test_lambda_overloads(); test_lambda_overloads();
test_singleton_variant(); test_singleton_variant();
test_call_nonconst_member();
test_lambda_overloads_capture(); test_lambda_overloads_capture();
test_lambda_overloads_sfinae(); test_lambda_overloads_sfinae();
test_match_singleton(); test_match_singleton();
test_match_overloads(); test_match_overloads();
test_match_overloads_capture(); test_match_overloads_capture();
test_match_overloads_init_capture();
test_match_overloads_otherwise();
test_match_move_out_of_variant();
} }
#undef HAS_CPP14_SUPPORT #undef HAS_CPP14_SUPPORT

View File

@ -1,4 +1,3 @@
#include <cstdlib> #include <cstdlib>
#include <iostream> #include <iostream>
#include <string> #include <string>
@ -64,12 +63,12 @@ struct calculator
int operator()(binary_op<add> const& binary) const int operator()(binary_op<add> const& binary) const
{ {
return util::apply_visitor(calculator(), binary.left) + util::apply_visitor(calculator(), binary.right); return util::apply_visitor(*this, binary.left) + util::apply_visitor(*this, binary.right);
} }
int operator()(binary_op<sub> const& binary) const int operator()(binary_op<sub> const& binary) const
{ {
return util::apply_visitor(calculator(), binary.left) - util::apply_visitor(calculator(), binary.right); return util::apply_visitor(*this, binary.left) - util::apply_visitor(*this, binary.right);
} }
}; };
@ -83,12 +82,12 @@ struct to_string
std::string operator()(binary_op<add> const& binary) const std::string operator()(binary_op<add> const& binary) const
{ {
return util::apply_visitor(to_string(), binary.left) + std::string("+") + util::apply_visitor(to_string(), binary.right); return util::apply_visitor(*this, binary.left) + std::string("+") + util::apply_visitor(*this, binary.right);
} }
std::string operator()(binary_op<sub> const& binary) const std::string operator()(binary_op<sub> const& binary) const
{ {
return util::apply_visitor(to_string(), binary.left) + std::string("-") + util::apply_visitor(to_string(), binary.right); return util::apply_visitor(*this, binary.left) + std::string("-") + util::apply_visitor(*this, binary.right);
} }
}; };

Some files were not shown because too many files have changed in this diff Show More