diff --git a/.github/workflows/cmake-ci.yml b/.github/workflows/cmake-ci.yml deleted file mode 100644 index 7302755..0000000 --- a/.github/workflows/cmake-ci.yml +++ /dev/null @@ -1,107 +0,0 @@ -# Copyright Agustin K-ballo Berge, Fusion Fenix 2020 -# -# Distributed under the Boost Software License, Version 1.0. (See accompanying -# file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -name: CMake - -on: - push: - branches: - paths: - - 'CMakeLists.txt' - - 'example/**' - - '.github/workflows/cmake-ci.yml' - pull_request: - -defaults: - run: - shell: bash - -jobs: - find_package: - name: find_package - ${{ matrix.os }} - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, macos-latest, windows-latest] - - steps: - - uses: actions/checkout@v1 - - - name: Configure library - run: | - mkdir build - cd build - cmake -DCMAKE_CXX_STANDARD=11 \ - -DCMAKE_INSTALL_PREFIX=${PWD}/install \ - .. - - - name: Install library - working-directory: build - run: | - cmake --install . - - - name: Configure example - working-directory: example - run: | - mkdir build - cd build - cmake -DCMAKE_CXX_STANDARD=11 \ - -DEggs.Invoke_DIR=${PWD}/../../build/install/lib/cmake/eggs.invoke \ - .. - - - name: Build example - working-directory: example/build - run: | - cmake --build . - - add_subdirectory: - name: add_subdirectory - ${{ matrix.os }} - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, macos-latest, windows-latest] - - steps: - - uses: actions/checkout@v1 - - - name: Configure example - working-directory: example - run: | - mkdir build - cd build - cmake -DCMAKE_CXX_STANDARD=11 \ - -DEggs.Invoke_SOURCE_DIR=${PWD}/../.. \ - .. - - - name: Build example - working-directory: example/build - run: | - cmake --build . - - fetch_content: - name: fetch_content - ${{ matrix.os }} - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, macos-latest, windows-latest] - - steps: - - uses: actions/checkout@v1 - - - name: Configure example - working-directory: example - run: | - mkdir build - cd build - cmake -DCMAKE_CXX_STANDARD=11 \ - .. - - - name: Build example - working-directory: example/build - run: | - cmake --build . diff --git a/.github/workflows/invoke-benchmark.yml b/.github/workflows/invoke-benchmark.yml deleted file mode 100644 index 54484cc..0000000 --- a/.github/workflows/invoke-benchmark.yml +++ /dev/null @@ -1,122 +0,0 @@ -# Copyright Agustin K-ballo Berge, Fusion Fenix 2020 -# -# Distributed under the Boost Software License, Version 1.0. (See accompanying -# file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -name: Eggs.Invoke Benchmark - -on: - push: - branches: - paths: - - 'CMakeLists.txt' - - 'benchmark/**' - - 'include/**' - - '.github/workflows/invoke-benchmark.yml' - pull_request: - -defaults: - run: - shell: bash - -jobs: - build: - name: ${{ matrix.config.name }} - runs-on: ${{ matrix.config.os }} - strategy: - fail-fast: false - matrix: - config: - - { - name: "Linux GCC 9", - os: ubuntu-latest, - generator: Ninja, - cc: "gcc-9", cxx: "g++-9", - cxxflags: "-Wall -Wextra -Werror", - buildflags: "-j1" - } - - { - name: "Linux Clang 9", - os: ubuntu-latest, - generator: Ninja, - cc: "clang-9", cxx: "clang++-9", - cxxflags: "-Wall -Wextra -Werror", - buildflags: "-j1" - } - - { - name: "macOS Clang", - os: macos-latest, - generator: Ninja, - cc: "clang", cxx: "clang++", - cxxflags: "-Wall -Wextra -Werror", - buildflags: "-j1" - } - - { - name: "Windows MSVC 2019", - os: windows-latest, - generator: Visual Studio 16 2019, - cc: "cl", cxx: "cl", - cxxflags: "-W4 -WX -permissive-", - buildflags: "-m:1" - } - - steps: - - uses: actions/checkout@v1 - - - uses: seanmiddleditch/gha-setup-ninja@master - - - name: Configure - env: - CC: ${{ matrix.config.cc }} - CXX: ${{ matrix.config.cxx }} - CXXFLAGS: ${{ matrix.config.cxxflags }} - run: | - mkdir build - cd build - cmake -G"${{ matrix.config.generator }}" \ - -DCMAKE_CXX_STANDARD=17 \ - -DCMAKE_CXX_EXTENSIONS=OFF \ - -DBUILD_BENCHMARKS=ON \ - -DBENCHMARK_INSTANTIATIONS=10000 \ - -DBUILD_EXAMPLE=OFF \ - -DBUILD_TESTING=OFF \ - .. - - - name: Benchmark - function - working-directory: build - run: | - cmake --build . --target benchmark.function \ - -- ${{ matrix.config.buildflags }} - - - name: Benchmark - member_object - working-directory: build - run: | - cmake --build . --target benchmark.member_object \ - -- ${{ matrix.config.buildflags }} - - - name: Benchmark - member_function - working-directory: build - run: | - cmake --build . --target benchmark.member_function \ - -- ${{ matrix.config.buildflags }} - - - name: Benchmark - callable - working-directory: build - run: | - cmake --build . --target benchmark.callable \ - -- ${{ matrix.config.buildflags }} - - - name: Generate benchmark reports - working-directory: build - if: ${{ matrix.config.generator == 'Ninja' }} - run: | - cmake --build . --target benchmark - - - name: Upload benchmark reports - if: ${{ matrix.config.generator == 'Ninja' }} - uses: actions/upload-artifact@v2 - with: - name: benchmark report - ${{ matrix.config.name }} - path: | - build/benchmark/benchmark.*.json - build/benchmark/reports/ diff --git a/.github/workflows/invoke-ci-cxx11.yml b/.github/workflows/invoke-ci-cxx11.yml deleted file mode 100644 index 8ac957e..0000000 --- a/.github/workflows/invoke-ci-cxx11.yml +++ /dev/null @@ -1,98 +0,0 @@ -# Copyright Agustin K-ballo Berge, Fusion Fenix 2020 -# -# Distributed under the Boost Software License, Version 1.0. (See accompanying -# file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -name: Eggs.Invoke C++11 - -on: - push: - branches: - paths: - - 'CMakeLists.txt' - - 'example/**' - - 'include/**' - - 'test/**' - - '.github/workflows/invoke-ci-cxx11.yml' - pull_request: - -defaults: - run: - shell: bash - -jobs: - build: - name: ${{ matrix.config.name }} - ${{ matrix.build_type }} - runs-on: ${{ matrix.config.os }} - strategy: - fail-fast: false - matrix: - config: - - { - name: "Linux GCC 9", - os: ubuntu-latest, - generator: Ninja, - cc: "gcc-9", cxx: "g++-9", - cxxflags: "-Wall -Wextra -Werror" - } - - { - name: "Linux Clang 9", - os: ubuntu-latest, - generator: Ninja, - cc: "clang-9", cxx: "clang++-9", - cxxflags: "-Wall -Wextra -Werror" - } - - { - name: "macOS Clang", - os: macos-latest, - generator: Ninja, - cc: "clang", cxx: "clang++", - cxxflags: "-Wall -Wextra -Werror" - } - - { - name: "Windows MSVC 2019", - os: windows-latest, - generator: Visual Studio 16 2019, - cc: "cl", cxx: "cl", - cxxflags: "-W4 -WX -permissive- -Zc:preprocessor -wd5105" - } - - { - name: "Windows MSVC 2019 (permissive)", - os: windows-latest, - generator: Visual Studio 16 2019, - cc: "cl", cxx: "cl", - cxxflags: "-W4 -WX" - } - build_type: [Debug, Release] - - steps: - - uses: actions/checkout@v1 - - - uses: seanmiddleditch/gha-setup-ninja@master - - - name: Configure - env: - CC: ${{ matrix.config.cc }} - CXX: ${{ matrix.config.cxx }} - CXXFLAGS: ${{ matrix.config.cxxflags }} - run: | - mkdir build - cd build - cmake -G"${{ matrix.config.generator }}" \ - -DCMAKE_CXX_STANDARD=11 \ - -DCMAKE_CXX_EXTENSIONS=OFF \ - -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \ - -DBUILD_BENCHMARKS=OFF \ - -DBUILD_EXAMPLE=ON \ - -DBUILD_TESTING=ON \ - .. - - - name: Build - working-directory: build - run: | - cmake --build . --config ${{ matrix.build_type }} - - - name: Test - working-directory: build - run: | - ctest --build-config ${{ matrix.build_type }} --output-on-failure diff --git a/.github/workflows/invoke-ci-cxx14.yml b/.github/workflows/invoke-ci-cxx14.yml deleted file mode 100644 index d35b731..0000000 --- a/.github/workflows/invoke-ci-cxx14.yml +++ /dev/null @@ -1,98 +0,0 @@ -# Copyright Agustin K-ballo Berge, Fusion Fenix 2020 -# -# Distributed under the Boost Software License, Version 1.0. (See accompanying -# file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -name: Eggs.Invoke C++14 - -on: - push: - branches: - paths: - - 'CMakeLists.txt' - - 'example/**' - - 'include/**' - - 'test/**' - - '.github/workflows/invoke-ci-cxx14.yml' - pull_request: - -defaults: - run: - shell: bash - -jobs: - build: - name: ${{ matrix.config.name }} - ${{ matrix.build_type }} - runs-on: ${{ matrix.config.os }} - strategy: - fail-fast: false - matrix: - config: - - { - name: "Linux GCC 9", - os: ubuntu-latest, - generator: Ninja, - cc: "gcc-9", cxx: "g++-9", - cxxflags: "-Wall -Wextra -Werror" - } - - { - name: "Linux Clang 9", - os: ubuntu-latest, - generator: Ninja, - cc: "clang-9", cxx: "clang++-9", - cxxflags: "-Wall -Wextra -Werror" - } - - { - name: "macOS Clang", - os: macos-latest, - generator: Ninja, - cc: "clang", cxx: "clang++", - cxxflags: "-Wall -Wextra -Werror" - } - - { - name: "Windows MSVC 2019", - os: windows-latest, - generator: Visual Studio 16 2019, - cc: "cl", cxx: "cl", - cxxflags: "-W4 -WX -permissive- -Zc:preprocessor -wd5105" - } - - { - name: "Windows MSVC 2019 (permissive)", - os: windows-latest, - generator: Visual Studio 16 2019, - cc: "cl", cxx: "cl", - cxxflags: "-W4 -WX" - } - build_type: [Debug, Release] - - steps: - - uses: actions/checkout@v1 - - - uses: seanmiddleditch/gha-setup-ninja@master - - - name: Configure - env: - CC: ${{ matrix.config.cc }} - CXX: ${{ matrix.config.cxx }} - CXXFLAGS: ${{ matrix.config.cxxflags }} - run: | - mkdir build - cd build - cmake -G"${{ matrix.config.generator }}" \ - -DCMAKE_CXX_STANDARD=14 \ - -DCMAKE_CXX_EXTENSIONS=OFF \ - -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \ - -DBUILD_BENCHMARKS=OFF \ - -DBUILD_EXAMPLE=ON \ - -DBUILD_TESTING=ON \ - .. - - - name: Build - working-directory: build - run: | - cmake --build . --config ${{ matrix.build_type }} - - - name: Test - working-directory: build - run: | - ctest --build-config ${{ matrix.build_type }} --output-on-failure diff --git a/.github/workflows/invoke-ci-cxx17.yml b/.github/workflows/invoke-ci-cxx17.yml deleted file mode 100644 index fababdc..0000000 --- a/.github/workflows/invoke-ci-cxx17.yml +++ /dev/null @@ -1,101 +0,0 @@ -# Copyright Agustin K-ballo Berge, Fusion Fenix 2020 -# -# Distributed under the Boost Software License, Version 1.0. (See accompanying -# file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -name: Eggs.Invoke C++17 - -on: - push: - branches: - paths: - - 'CMakeLists.txt' - - 'benchmark/**' - - 'example/**' - - 'include/**' - - 'test/**' - - '.github/workflows/invoke-ci-cxx17.yml' - pull_request: - -defaults: - run: - shell: bash - -jobs: - build: - name: ${{ matrix.config.name }} - ${{ matrix.build_type }} - runs-on: ${{ matrix.config.os }} - strategy: - fail-fast: false - matrix: - config: - - { - name: "Linux GCC 9", - os: ubuntu-latest, - generator: Ninja, - cc: "gcc-9", cxx: "g++-9", - cxxflags: "-Wall -Wextra -Werror" - } - - { - name: "Linux Clang 9", - os: ubuntu-latest, - generator: Ninja, - cc: "clang-9", cxx: "clang++-9", - cxxflags: "-Wall -Wextra -Werror" - } - - { - name: "macOS Clang", - os: macos-latest, - generator: Ninja, - cc: "clang", cxx: "clang++", - cxxflags: "-Wall -Wextra -Werror" - } - - { - name: "Windows MSVC 2019", - os: windows-latest, - generator: Visual Studio 16 2019, - cc: "cl", cxx: "cl", - cxxflags: "-W4 -WX -permissive- -Zc:preprocessor -wd5105" - } - - { - name: "Windows MSVC 2019 (permissive)", - os: windows-latest, - generator: Visual Studio 16 2019, - cc: "cl", cxx: "cl", - cxxflags: "-W4 -WX" - } - build_type: [Debug, Release] - - steps: - - uses: actions/checkout@v1 - - - uses: seanmiddleditch/gha-setup-ninja@master - - - name: Configure - env: - CC: ${{ matrix.config.cc }} - CXX: ${{ matrix.config.cxx }} - CXXFLAGS: ${{ matrix.config.cxxflags }} - run: | - mkdir build - cd build - cmake -G"${{ matrix.config.generator }}" \ - -DCMAKE_CXX_STANDARD=17 \ - -DCMAKE_CXX_EXTENSIONS=OFF \ - -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \ - -DBUILD_BENCHMARKS=ON \ - -DBENCHMARK_INSTANTIATIONS=1 \ - -DBUILD_EXAMPLE=ON \ - -DBUILD_TESTING=ON \ - .. - - - name: Build - working-directory: build - run: | - cmake --build . --config ${{ matrix.build_type }} - cmake --build . --target benchmark --config ${{ matrix.build_type }} - - - name: Test - working-directory: build - run: | - ctest --build-config ${{ matrix.build_type }} --output-on-failure diff --git a/.github/workflows/invoke-ci-cxx20.yml b/.github/workflows/invoke-ci-cxx20.yml deleted file mode 100644 index c6cb652..0000000 --- a/.github/workflows/invoke-ci-cxx20.yml +++ /dev/null @@ -1,101 +0,0 @@ -# Copyright Agustin K-ballo Berge, Fusion Fenix 2020 -# -# Distributed under the Boost Software License, Version 1.0. (See accompanying -# file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -name: Eggs.Invoke C++20 - -on: - push: - branches: - paths: - - 'CMakeLists.txt' - - 'benchmark/**' - - 'example/**' - - 'include/**' - - 'test/**' - - '.github/workflows/invoke-ci-cxx20.yml' - pull_request: - -defaults: - run: - shell: bash - -jobs: - build: - name: ${{ matrix.config.name }} - ${{ matrix.build_type }} - runs-on: ${{ matrix.config.os }} - strategy: - fail-fast: false - matrix: - config: - - { - name: "Linux GCC 9", - os: ubuntu-latest, - generator: Ninja, - cc: "gcc-9", cxx: "g++-9", - cxxflags: "-Wall -Wextra -Werror" - } - - { - name: "Linux Clang 9", - os: ubuntu-latest, - generator: Ninja, - cc: "clang-9", cxx: "clang++-9", - cxxflags: "-Wall -Wextra -Werror" - } - - { - name: "macOS Clang", - os: macos-latest, - generator: Ninja, - cc: "clang", cxx: "clang++", - cxxflags: "-Wall -Wextra -Werror" - } - - { - name: "Windows MSVC 2019", - os: windows-latest, - generator: Visual Studio 16 2019, - cc: "cl", cxx: "cl", - cxxflags: "-W4 -WX -permissive- -Zc:preprocessor -wd5105" - } - - { - name: "Windows MSVC 2019 (permissive)", - os: windows-latest, - generator: Visual Studio 16 2019, - cc: "cl", cxx: "cl", - cxxflags: "-W4 -WX" - } - build_type: [Debug, Release] - - steps: - - uses: actions/checkout@v1 - - - uses: seanmiddleditch/gha-setup-ninja@master - - - name: Configure - env: - CC: ${{ matrix.config.cc }} - CXX: ${{ matrix.config.cxx }} - CXXFLAGS: ${{ matrix.config.cxxflags }} - run: | - mkdir build - cd build - cmake -G"${{ matrix.config.generator }}" \ - -DCMAKE_CXX_STANDARD=20 \ - -DCMAKE_CXX_EXTENSIONS=OFF \ - -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \ - -DBUILD_BENCHMARKS=ON \ - -DBENCHMARK_INSTANTIATIONS=1 \ - -DBUILD_EXAMPLE=ON \ - -DBUILD_TESTING=ON \ - .. - - - name: Build - working-directory: build - run: | - cmake --build . --config ${{ matrix.build_type }} - cmake --build . --target benchmark --config ${{ matrix.build_type }} - - - name: Test - working-directory: build - run: | - ctest --build-config ${{ matrix.build_type }} --output-on-failure diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index 916bb7b..0000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,75 +0,0 @@ -# Eggs.Invoke -# -# Copyright Agustin K-ballo Berge, Fusion Fenix 2017-2020 -# -# Distributed under the Boost Software License, Version 1.0. (See accompanying -# file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -cmake_minimum_required(VERSION 3.0...3.18) - -project(Eggs.Invoke CXX) - -list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) - -set_property(GLOBAL PROPERTY USE_FOLDERS ON) - -include(option_str) -if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) - include(CTest) # option(BUILD_TESTING ...) - option(BUILD_BENCHMARKS "Build the benchmarks" OFF) - option_str(BENCHMARK_INSTANTIATIONS "Number of instantiations for benchmarks" 10000) - option(BUILD_EXAMPLE "Build the example" ON) - option(ENABLE_INSTALL "Enable installing the library" ON) -else() - option(EGGS_INVOKE_BUILD_BENCHMARKS "Build the benchmarks" OFF) - option_str(EGGS_INVOKE_BENCHMARK_INSTANTIATIONS "Number of instantiations for benchmarks" 10000) - option(EGGS_INVOKE_BUILD_EXAMPLE "Build the example" OFF) - option(EGGS_INVOKE_BUILD_TESTING "Build the testing tree" OFF) - option(EGGS_INVOKE_ENABLE_INSTALL "Enable installing the library" OFF) - set(BUILD_BENCHMARKS ${EGGS_INVOKE_BUILD_BENCHMARKS}) - set(BENCHMARK_INSTANTIATIONS ${EGGS_INVOKE_BENCHMARK_INSTANTIATIONS}) - set(BUILD_EXAMPLE ${EGGS_INVOKE_BUILD_EXAMPLE}) - set(BUILD_TESTING ${EGGS_INVOKE_BUILD_TESTING}) - set(ENABLE_INSTALL ${EGGS_INVOKE_ENABLE_INSTALL}) -endif() - -include(GNUInstallDirs) - -# Build -add_library(_eggs_invoke INTERFACE) -target_include_directories(_eggs_invoke INTERFACE - $ - $) -set_target_properties(_eggs_invoke - PROPERTIES EXPORT_NAME Eggs::Invoke) - -add_library(Eggs::Invoke ALIAS _eggs_invoke) - -# Benchmarks -if (BUILD_BENCHMARKS) - add_subdirectory(benchmark) -endif() - -# Example -if (BUILD_EXAMPLE) - add_subdirectory(example) -endif() - -# Test -if (BUILD_TESTING) - if (NOT CMAKE_TESTING_ENABLED) - message(AUTHOR_WARNING "Tests enabled but enable_testing() not called") - endif() - add_subdirectory(test) -endif() - -# Install -if (ENABLE_INSTALL) - install(DIRECTORY include/eggs - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) - - install(TARGETS _eggs_invoke EXPORT _targets) - install(EXPORT _targets - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/eggs.invoke - FILE eggs.invoke-config.cmake) -endif() diff --git a/README.md b/README.md index 646f041..611d271 100644 --- a/README.md +++ b/README.md @@ -3,189 +3,8 @@ ## Introduction ## -**Eggs.Invoke** is a **C++11/14/17/20** single-header implementation of -`INVOKE` and its related facilities. See the documentation at -http://eggs-cpp.github.io/invoke/. - -## Reference ## - -#### Definitions - -Define `INVOKE(f, t1, t2, ..., tN)` as follows: - -- `(t1.*f)(t2, ..., tN)` when `f` is a pointer to a member function of a - class `T` and `std::is_base_of_v>` - is `true`; - -- `(t1.get().*f)(t2, ..., tN)` when `f` is a pointer to a member function of a - class `T` and `std::remove_cvref_t` is a specialization of - `std::reference_wrapper`; - -- `((*t1).*f)(t2, ..., tN)` when `f` is a pointer to a member function of a - class `T` and `t1` does not satisfy the previous two items; - -- `t1.*f` when `N == 1` and `f` is a pointer to data member of a class `T` and - `std::is_base_of_v>` is `true`; - -- `t1.get().*f` when `N == 1` and `f` is a pointer to data member of a class - `T` and `std::remove_cvref_t` is a specialization of - `std::reference_wrapper`; - -- `(*t1).*f` when `N == 1` and `f` is a pointer to data member of a class `T` - and `t1` does not satisfy the previous two items; - -- `f(t1, t2, ..., tN)` in all other cases. - -Define `INVOKE(f, t1, t2, ..., tN)` as `static_cast(INVOKE(f, t1, t2, -..., tN))` if `R` is _cv_ `void`, otherwise `INVOKE(f, t1, t2, ..., tN)` -implicitly converted to `R`. - -#### Function template `eggs::invoke` - -```cpp -template -constexpr eggs::invoke_result_t invoke(F&& f, Args&&... args) - noexcept(eggs::is_nothrow_invocable_v); -``` - -- _Returns_: `INVOKE(std::forward(f), std::forward(args)...)`. - -- _Remarks_: This function shall not participate in overload resolution unless - `eggs::is_invocable_v` is `true`. - -#### Function template `eggs::invoke_r` - -```cpp -template // (extension) -constexpr R eggs::invoke_r(F&& f, Args&&... args) - noexcept(eggs::is_nothrow_invocable_r_v); -``` - -- _Returns_: `INVOKE(std::forward(f), std::forward(args)...)`. - -- _Remarks_: This function shall not participate in overload resolution unless - `eggs::is_invocable_r_v` is `true`. - -#### Transformation Trait `eggs::invoke_result` - -```cpp -template struct invoke_result; -``` - -- _Comments_: If the expression `INVOKE(std::declval(), - std::declval()...)` is well-formed when treated as an unevaluated - operand, the member typedef `type` names the type `decltype(INVOKE(std::declval(), - std::declval()...))`; otherwise, there shall be no member `type`. - Access checking is performed as if in a context unrelated to `Fn` and - `ArgTypes`. Only the validity of the immediate context of the expression is - considered. - -- _Preconditions_: `Fn` and all types in the template parameter pack `ArgTypes` - are complete types, _cv_ `void`, or arrays of unknown bound. - -```cpp -template -using invoke_result_t = typename invoke_result::type; -``` - -#### Unary Type Traits `eggs::is_invocable` - -```cpp -template struct is_invocable; -``` - -- _Condition_: The expression `INVOKE(std::declval(), - std::declval()...)` is well-formed when treated as an unevaluated - operand. - -- _Comments_: `Fn` and all types in the template parameter pack `ArgTypes` - shall be complete types, _cv_ `void`, or arrays of unknown bound. - -```cpp -template // (C++14) -inline constexpr bool is_invocable_v = - eggs::is_invocable::value; -``` - -#### Unary Type Traits `eggs::is_invocable_r` - -```cpp -template struct is_invocable_r; -``` - -- _Condition_: The expression `INVOKE(std::declval(), - std::declval()...)` is well-formed when treated as an unevaluated - operand. - -- _Comments_: `Fn`, `R`, and all types in the template parameter pack - `ArgTypes` shall be complete types, _cv_ `void`, or arrays of unknown bound. - -```cpp -template // (C++14) -inline constexpr bool is_invocable_r_v = - eggs::is_invocable_r::value; -``` - -#### Unary Type Traits `eggs::is_nothrow_invocable` - -```cpp -template struct is_nothrow_invocable; -``` - -- _Condition_: `eggs::is_invocable_v` is `true` and the - expression `INVOKE(std::declval(), std::declval()...)` is - known not to throw any exceptions. - -- _Comments_: `Fn` and all types in the template parameter pack `ArgTypes` - shall be complete types, _cv_ `void`, or arrays of unknown bound. - -```cpp -template // (C++14) -inline constexpr bool is_nothrow_invocable_v = - eggs::is_nothrow_invocable::value; -``` - -#### Unary Type Traits `eggs::is_nothrow_invocable_r` - -```cpp -template struct is_nothrow_invocable_r; -``` - -- _Condition_: `eggs::is_invocable_r_v` is `true` and the - expression `INVOKE(std::declval(), std::declval()...)` is - known not to throw any exceptions. - -- _Comments_: `Fn`, `R`, and all types in the template parameter pack - `ArgTypes` shall be complete types, _cv_ `void`, or arrays of unknown bound. - -```cpp -template // (C++14) -inline constexpr bool is_nothrow_invocable_r_v = - eggs::is_nothrow_invocable_r::value; -``` - -#### Function-like macro `EGGS_INVOKE` - -```cpp -#define EGGS_INVOKE(F, ...) // (extension) -``` - -- _Returns_: `INVOKE(F __VA_OPT__(,) __VA_ARGS__)`. - -#### Function-like macro `EGGS_INVOKE_R` - -```cpp -#define EGGS_INVOKE_R(R, F, ...) // (extension) -``` - -- _Returns_: `INVOKE(F __VA_OPT__(,) __VA_ARGS__)`. - -## CI Status ## - -- C++11: ![](https://github.com/eggs-cpp/invoke/workflows/Eggs.Invoke%20C++11/badge.svg?branch=master) -- C++14: ![](https://github.com/eggs-cpp/invoke/workflows/Eggs.Invoke%20C++14/badge.svg?branch=master) -- C++17: ![](https://github.com/eggs-cpp/invoke/workflows/Eggs.Invoke%20C++17/badge.svg?branch=master) -- C++20: ![](https://github.com/eggs-cpp/invoke/workflows/Eggs.Invoke%20C++20/badge.svg?branch=master) +**Eggs.Invoke** is a **C++17** implementation of `INVOKE` and its related +facilities. --- diff --git a/benchmark.html b/benchmark.html new file mode 100644 index 0000000..6cf9619 --- /dev/null +++ b/benchmark.html @@ -0,0 +1,377 @@ + + + + + + + Eggs.Invoke + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+

These benchmarks measure the build overhead (compilation time, memory usage, object size) introduced by the use of different implementations of the INVOKE abstraction.

+
+ +
+

function (see Source Code)

+
+template <int I>
+int fun(...) { return I; }
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
CasePattern
plain call(&fun<I>)(1, 2, 3)
std::invokestd::invoke(&fun<I>, 1, 2, 3)
eggs::invokeeggs::invoke(&fun<I>, 1, 2, 3)
EGGS_INVOKEEGGS_INVOKE(&fun<I>, 1, 2, 3)
+ +

member_object (see Source Code)

+
template <int I>
+struct mem
+{
+    int obj;
+};
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
CasePattern
plain callmem<I>{}.*(&mem<I>::obj)
std::invokestd::invoke(&mem<I>::obj, mem<I>{})
eggs::invokeeggs::invoke(&mem<I>::obj, mem<I>{})
EGGS_INVOKEEGGS_INVOKE(&mem<I>::obj, mem<I>{})
+ +

member_function (see Source Code)

+
template <int I>
+struct mem
+{
+    int fun(...) { return I; };
+};
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
CasePattern
plain call(mem<I>{}.*(&mem<I>::fun))(1, 2, 3)
std::invokestd::invoke(&mem<I>::fun, mem<I>{}, 1, 2, 3)
eggs::invokeeggs::invoke(&mem<I>::fun, mem<I>{}, 1, 2, 3)
EGGS_INVOKEEGGS_INVOKE(&mem<I>::fun, mem<I>{}, 1, 2, 3)
+ +

callable (see Source Code)

+
template <int I>
+struct callable {
+    template <typename ...Args>
+    auto operator()(Args&&... args) const
+        noexcept(noexcept(fun<I>(std::forward<Args>(args)...)))
+     -> decltype(fun<I>(std::forward<Args>(args)...))
+    {
+        return fun<I>(std::forward<Args>(args)...);
+    }
+};
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
CasePattern
plain callcallable<I>{}(1, 2, 3)
std::invokestd::invoke(callable<I>{}, 1, 2, 3)
eggs::invokeeggs::invoke(callable<I>{}, 1, 2, 3)
EGGS_INVOKEEGGS_INVOKE(callable<I>{}, 1, 2, 3)
+

Each pattern is instantiated for different values of I, and aspects of the build are captured: compilation time, memory usage, object size. Results for each benchmark are provided both as absolute values, as well as relative values based on the plain call case.

+

These benchmarks do NOT look at runtime performance. INVOKE is a zero-cost abstraction: no runtime overhead is introduced by its use in an optimized build.

+
+ +
+
+ +

Results

+
+
    +
    +
    + +
    + + + + + +
    +

    + Copyright + Agustín Bergé, + Fusion Fenix 2017-2020 +

    + +

    + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +

    +
    + + diff --git a/benchmark/CMakeLists.txt b/benchmark/CMakeLists.txt deleted file mode 100644 index e2b5ac9..0000000 --- a/benchmark/CMakeLists.txt +++ /dev/null @@ -1,145 +0,0 @@ -# Eggs.Invoke -# -# Copyright Agustin K-ballo Berge, Fusion Fenix 2017-2020 -# -# Distributed under the Boost Software License, Version 1.0. (See accompanying -# file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -cmake_minimum_required(VERSION 3.4...3.18) - -set(_benchmark_report YES) -if (NOT CMAKE_GENERATOR MATCHES "Make|Ninja") - set(_benchmark_report NO) - set(_benchmark_report_warning - "CXX_COMPILER_LAUNCHER not supported by this generator, " - "needed for generating benchmark reports.") -else() - find_package(Python3 3.6) - if (NOT Python3_FOUND) - set(_benchmark_report NO) - set(_benchmark_report_warning - "Python3 not found, needed for generating benchmark reports.") - endif() -endif() - -function(add_benchmark NAME INPUT) - cmake_parse_arguments("ARG" - "" - "INSTANTIATIONS;OUTPUT;REPORT_TEMPLATE" - "CASES" - ${ARGN}) - if (NOT DEFINED ARG_INSTANTIATIONS) - set(ARG_INSTANTIATIONS 10000) - endif() - if (NOT DEFINED ARG_OUTPUT) - set(ARG_OUTPUT ${NAME}.html) - endif() - - set(_instantiations "") - foreach(_i RANGE 1 ${ARG_INSTANTIATIONS}) - string(APPEND _instantiations "\n benchmark<${_i}>();") - endforeach() - - set(_cases) - set(_labels) - while (ARG_CASES) - list(GET ARG_CASES 0 _case) - list(APPEND _cases ${_case}) - list(GET ARG_CASES 1 _label) - list(APPEND _labels ${_label}) - list(REMOVE_AT ARG_CASES 0 1) - endwhile() - list(APPEND _cases 0) - list(APPEND _labels "baseline") - - set(_sources) - get_filename_component(_base ${INPUT} NAME_WE) - foreach(_benchmark ${_cases}) - set(_output ${CMAKE_CURRENT_BINARY_DIR}/${_base}.${_benchmark}.cpp) - set(BENCHMARK_INSTANTIATIONS " -#if !defined BENCHMARK_WARMUP -void benchmark${_benchmark}() {${_instantiations}\n} -#endif -") - configure_file(${INPUT} ${_output} @ONLY) - - set_source_files_properties(${_output} PROPERTIES - COMPILE_DEFINITIONS BENCHMARK=${_benchmark} - INCLUDE_DIRECTORIES ${CMAKE_CURRENT_BINARY_DIR}) - list(APPEND _sources ${input} ${_output}) - endforeach() - - add_library(${NAME} OBJECT EXCLUDE_FROM_ALL ${_sources}) - if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") - target_compile_options(${NAME} PRIVATE -ftime-report) - elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - target_compile_options(${NAME} PRIVATE /bigobj /Bt+) - endif() - set_target_properties(${NAME} PROPERTIES - JOB_POOL_COMPILE "console") - - if (NOT _benchmark_report) - message(WARNING ${_benchmark_report_warning}) - else() - string(REPLACE ";" "|" _cases "${_cases}") - string(REPLACE ";" "|" _labels "${_labels}") - set_property(TARGET ${NAME} - PROPERTY CXX_COMPILER_LAUNCHER - ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/compiler_launcher.py - --compiler_id=${CMAKE_CXX_COMPILER_ID} - --compiler_version=${CMAKE_CXX_COMPILER_VERSION} - --target=${NAME} - --cases=${_cases} - --labels=${_labels} - --instantiations=${ARG_INSTANTIATIONS} - --object= - --) - - get_filename_component(INPUT ${INPUT} ABSOLUTE) - get_filename_component(ARG_REPORT_TEMPLATE ${ARG_REPORT_TEMPLATE} ABSOLUTE) - get_filename_component(ARG_OUTPUT ${ARG_OUTPUT} ABSOLUTE - BASE_DIR ${CMAKE_CURRENT_BINARY_DIR}) - add_custom_command( - OUTPUT ${ARG_OUTPUT} - COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/generate_report.py - --target=${NAME} - --source=${INPUT} - --instantiations=${ARG_INSTANTIATIONS} - --output=${ARG_OUTPUT} - --template=${ARG_REPORT_TEMPLATE} - --objects="$" - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS ${NAME} ${ARG_REPORT_TEMPLATE} $) - - add_custom_target(${NAME}.report DEPENDS ${ARG_OUTPUT}) - set_property(TARGET ${NAME}.report PROPERTY FOLDER "benchmark/report") - endif() -endfunction() - -set(_benchmarks - callable - function - member_function - member_object) - -add_custom_target(benchmark) -set_property(TARGET benchmark PROPERTY FOLDER "benchmark") - -foreach(_benchmark ${_benchmarks}) - add_benchmark(benchmark.${_benchmark} ${_benchmark}.cpp.in - INSTANTIATIONS ${BENCHMARK_INSTANTIATIONS} - REPORT_TEMPLATE template/report.html.in - OUTPUT reports/${_benchmark}.html - CASES - 1 "plain call" - 2 "std::invoke" - 3 "eggs::invoke" - 4 "EGGS_INVOKE") - target_link_libraries(benchmark.${_benchmark} Eggs::Invoke) - set_property(TARGET benchmark.${_benchmark} PROPERTY FOLDER "benchmark") - - add_dependencies(benchmark benchmark.${_benchmark}) - if (_benchmark_report) - add_dependencies(benchmark benchmark.${_benchmark}.report) - endif() -endforeach() diff --git a/benchmark/README.md b/benchmark/README.md deleted file mode 100644 index 73d8c96..0000000 --- a/benchmark/README.md +++ /dev/null @@ -1,32 +0,0 @@ -**Eggs.Invoke** -================== - -See results at http://eggs-cpp.github.io/invoke/benchmark.html. - -## Benchmark ## - -These benchmarks measure the build overhead (compilation time, memory usage, -object size) introduced by the use of different implementations of the -`INVOKE` abstraction. - -These benchmarks do NOT look at runtime performance. `INVOKE` is a zero-cost -abstraction: no runtime overhead is introduced by its use in an _optimized_ -build. - -## Requirements ## - -**C++17** is required for benchmarking `std::invoke`. - -Python 3.6 and a Makefile or Ninja CMake generator is required for generating -benchmark reports. - -## CI Status ## - -![](https://github.com/eggs-cpp/invoke/workflows/Eggs.Invoke%20Benchmark/badge.svg?branch=master) - ---- - -> Copyright _Agustín Bergé_, _Fusion Fenix_ 2017-2020 -> -> Distributed under the Boost Software License, Version 1.0. (See accompanying -> file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/benchmark/callable.cpp.in b/benchmark/callable.cpp.in deleted file mode 100644 index cedd177..0000000 --- a/benchmark/callable.cpp.in +++ /dev/null @@ -1,37 +0,0 @@ -#if BENCHMARK == 2 -#include -#elif BENCHMARK == 3 || BENCHMARK == 4 -#include -#endif - -#include - -template -static int fun(...) { return I; } - -template -struct callable { - template - auto operator()(Args&&... args) const - noexcept(noexcept(fun(std::forward(args)...))) - -> decltype(fun(std::forward(args)...)) - { - return fun(std::forward(args)...); - } -}; - -template -static void benchmark() -{ -#if BENCHMARK == 1 - callable{}(0, 1, 2); -#elif BENCHMARK == 2 - std::invoke(callable{}, 0, 1, 2); -#elif BENCHMARK == 3 - eggs::invoke(callable{}, 0, 1, 2); -#elif BENCHMARK == 4 - EGGS_INVOKE(callable{}, 0, 1, 2); -#endif -} - -@BENCHMARK_INSTANTIATIONS@ diff --git a/benchmark/compiler_launcher.py b/benchmark/compiler_launcher.py deleted file mode 100644 index 686834f..0000000 --- a/benchmark/compiler_launcher.py +++ /dev/null @@ -1,143 +0,0 @@ -# Eggs.Invoke -# -# Copyright Agustin K-ballo Berge, Fusion Fenix 2020 -# -# Distributed under the Boost Software License, Version 1.0. (See accompanying -# file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -import argparse -import json -import os -import pathlib -import re -import subprocess -import sys -import time - -# ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/compiler_launcher.py -# --compiler_id=${CMAKE_CXX_COMPILER_ID} -# --compiler_version=${CMAKE_CXX_COMPILER_VERSION} -# --target=${NAME} -# --cases=0|1|... -# --labels=Baseline|Label 1|... -# --instantiations=${ARG_INSTANTIATIONS} -# --object= -# -- ... -if __name__ == '__main__': - parser = argparse.ArgumentParser() - parser.add_argument('cmd', nargs='+') - parser.add_argument('--compiler_id', required=True) - parser.add_argument('--compiler_version', required=True) - parser.add_argument('--target', required=True) - parser.add_argument('--cases', required=True) - parser.add_argument('--labels', required=True) - parser.add_argument('--instantiations', required=True) - parser.add_argument('--object', required=True) - args = parser.parse_args() - - target = args.target - benchmark = next(x for x in args.cmd if x.startswith('DBENCHMARK=', 1))[len('-DBENCHMARK='):] - case_index = args.cases.split('|').index(benchmark) - label = args.labels.split('|')[case_index] - instantiations = args.instantiations - #print(f'subprocess.run({args.cmd})') - - # warm up - process = subprocess.Popen(args.cmd + ['-DBENCHMARK_WARMUP'], - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - universal_newlines=True) - try: - stdout, stderr = process.communicate(input) - except: - process.kill() - raise - returncode = process.poll() - if returncode != 0: - print(stdout) - sys.exit(returncode) - - # run compiler - start_time = time.time() - process = subprocess.Popen(args.cmd, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - universal_newlines=True) - try: - stdout, stderr = process.communicate(input) - except: - process.kill() - raise - returncode = process.poll() - end_time = time.time() - - print(stdout) - if returncode != 0: - sys.exit(returncode) - - # extract information - compilation_time = end_time - start_time - memory_usage = '-' - object_size = os.path.getsize(args.object) - - try: - import resource - rusage = resource.getrusage(resource.RUSAGE_CHILDREN) - compilation_time = rusage.ru_utime + rusage.ru_stime - memory_usage = rusage.ru_maxrss - except ImportError: - pass - - if args.compiler_id == 'GNU': - # TOTAL : kB - m = re.search( - '^ TOTAL +: +([0-9.]+) +([0-9.]+) +([0-9.]+) +([0-9]+) kB$', - stdout, - re.MULTILINE) - if m: - user_time = float(m.group(1)) - system_time = float(m.group(2)) - compilation_time = user_time + system_time - wall_time = float(m.group(3)) - memory_usage = int(m.group(4)) - elif 'Clang' in args.compiler_id: - pos = stdout.find("Clang front-end time report") - if pos != -1: - # (100.0%) (100.0%) (100.0%) (100.0%) Total - m = re.search( - '^ +([0-9.]+) +\\(100.0%\\) +([0-9.]+) +\\(100.0%\\) +([0-9.]+) +\\(100.0%\\) +([0-9.]+) +\\(100.0%\\) +Total$', - stdout[pos:], re.MULTILINE) - if m: - user_time = float(m.group(1)) - system_time = float(m.group(2)) - compilation_time = float(m.group(3)) - wall_time = float(m.group(4)) - elif args.compiler_id == 'MSVC': - # time(*\c1xx.dll)=s < - > BB [] - # time(*\c2.dll)=s < - > BB [] - compilation_time = 0.0 - for m in re.finditer( - '^time\\(.*\\)=([0-9.]+)s', - stdout, re.MULTILINE): - compilation_time += float(m.group(1)) - - # print report - print(f'Benchmark: {target}/{benchmark}, {label}') - print(f'Instantiations: {instantiations}') - print(f'Compilation time: {compilation_time} s') - print(f'Memory usage: {memory_usage} kB') - print(f'Object size: {object_size} B') - - # dump to json - report = { - 'target': target, - 'benchmark': int(benchmark), - 'label': label, - 'compilation_time': compilation_time, - 'memory_usage': memory_usage * 1024 if memory_usage != '-' else '-', - 'object_size': object_size, - } - - pathlib.Path(args.target).parent.mkdir(parents=True, exist_ok=True) - with open(args.object + '.benchmark.json', 'w') as file: - json.dump(report, file) diff --git a/benchmark/function.cpp.in b/benchmark/function.cpp.in deleted file mode 100644 index b9e7d65..0000000 --- a/benchmark/function.cpp.in +++ /dev/null @@ -1,24 +0,0 @@ -#if BENCHMARK == 2 -#include -#elif BENCHMARK == 3 || BENCHMARK == 4 -#include -#endif - -template -static int fun(...) { return I; } - -template -static void benchmark() -{ -#if BENCHMARK == 1 - (&fun)(0, 1, 2); -#elif BENCHMARK == 2 - std::invoke(&fun, 0, 1, 2); -#elif BENCHMARK == 3 - eggs::invoke(&fun, 0, 1, 2); -#elif BENCHMARK == 4 - EGGS_INVOKE(&fun, 0, 1, 2); -#endif -} - -@BENCHMARK_INSTANTIATIONS@ diff --git a/benchmark/generate_report.py b/benchmark/generate_report.py deleted file mode 100644 index 1993bd3..0000000 --- a/benchmark/generate_report.py +++ /dev/null @@ -1,92 +0,0 @@ -# Eggs.Invoke -# -# Copyright Agustin K-ballo Berge, Fusion Fenix 2020 -# -# Distributed under the Boost Software License, Version 1.0. (See accompanying -# file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -import argparse -import html -import json -import os -import pathlib -import re - -# ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/generate_report.py -# --target=${NAME} -# --source=${INPUT} -# --instantiations=${ARG_INSTANTIATIONS} -# --output=${OUTPUT} -# --template=${ARG_REPORT_TEMPLATE} -# --objects="$" -if __name__ == '__main__': - parser = argparse.ArgumentParser() - parser.add_argument('--target', required=True) - parser.add_argument('--source', required=True) - parser.add_argument('--instantiations', required=True) - parser.add_argument('--output', required=True) - parser.add_argument('--template', required=True) - parser.add_argument('--objects', required=True) - args = parser.parse_args() - - reports = [] - for object in args.objects.split(';'): - with open(object + '.benchmark.json', 'r') as file: - report = json.load(file) - del report['target'] - - if (report['benchmark'] == 0): - baseline = report - else: - reports.append(report) - - datum = sorted(reports, key=lambda x: x['benchmark']) - DATUM = json.dumps({ 'values' : reports }, indent=2) - - compilation_time = { - 'field': 'compilation_time', - 'key': 'Compilation time', - 'baseline': baseline['compilation_time'], - 'format': ',.2f', - 'unit': 's' - } - memory_usage = { - 'field': 'memory_usage', - 'key': 'Memory usage', - 'baseline': baseline['memory_usage'], - 'format': '.5s', - 'unit': 'B' - } - object_size = { - 'field': 'object_size', - 'key': 'Object size', - 'baseline': baseline['object_size'], - 'format': '.5s', - 'unit': 'B' - } - aspects = [compilation_time, memory_usage, object_size] - ASPECTS = json.dumps(aspects, indent=2) - - pathlib.Path(args.target).parent.mkdir(parents=True, exist_ok=True) - with open(args.target + '.json', 'w') as file: - json.dump({ 'aspects': aspects, 'values': reports }, file) - - with open(args.source, 'r') as file: - source = file.read() - source = source.replace('@BENCHMARK_INSTANTIATIONS@', '').rstrip() - SOURCE_CODE = html.escape(source) - - INSTANTIATIONS = args.instantiations; - - template_dir = os.path.dirname(args.template) - def INCLUDE(path): - path = os.path.join(template_dir, path) - with open(path, 'r') as file: - return file.read() - - with open(args.template, 'r') as file: - template = file.read() - output = re.sub(r'@(.*)@', lambda m: str(eval(m.group(1))), template) - - pathlib.Path(args.output).parent.mkdir(parents=True, exist_ok=True) - with open(args.output, 'w') as file: - file.write(output) diff --git a/benchmark/member_function.cpp.in b/benchmark/member_function.cpp.in deleted file mode 100644 index 6f0d8a9..0000000 --- a/benchmark/member_function.cpp.in +++ /dev/null @@ -1,27 +0,0 @@ -#if BENCHMARK == 2 -#include -#elif BENCHMARK == 3 || BENCHMARK == 4 -#include -#endif - -template -struct mem -{ - int fun(...) { return I; }; -}; - -template -static void benchmark() -{ -#if BENCHMARK == 1 - (mem{}.*(&mem::fun))(0, 1, 2); -#elif BENCHMARK == 2 - std::invoke(&mem::fun, mem{}, 0, 1, 2); -#elif BENCHMARK == 3 - eggs::invoke(&mem::fun, mem{}, 0, 1, 2); -#elif BENCHMARK == 4 - EGGS_INVOKE(&mem::fun, mem{}, 0, 1, 2); -#endif -} - -@BENCHMARK_INSTANTIATIONS@ diff --git a/benchmark/member_object.cpp.in b/benchmark/member_object.cpp.in deleted file mode 100644 index 0c88803..0000000 --- a/benchmark/member_object.cpp.in +++ /dev/null @@ -1,27 +0,0 @@ -#if BENCHMARK == 2 -#include -#elif BENCHMARK == 3 || BENCHMARK == 4 -#include -#endif - -template -struct mem -{ - int obj; -}; - -template -static void benchmark() -{ -#if BENCHMARK == 1 - (void)(mem{}.*(&mem::obj)); -#elif BENCHMARK == 2 - std::invoke(&mem::obj, mem{}); -#elif BENCHMARK == 3 - eggs::invoke(&mem::obj, mem{}); -#elif BENCHMARK == 4 - EGGS_INVOKE(&mem::obj, mem{}); -#endif -} - -@BENCHMARK_INSTANTIATIONS@ diff --git a/benchmark/template/prism.min.css b/benchmark/template/prism.min.css deleted file mode 100644 index 8c4cc05..0000000 --- a/benchmark/template/prism.min.css +++ /dev/null @@ -1 +0,0 @@ -code[class*=language-],pre[class*=language-]{color:#000;background:0 0;text-shadow:0 1px #fff;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow:none;background:#b3d4fc}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow:none;background:#b3d4fc}@media print{code[class*=language-],pre[class*=language-]{text-shadow:none}}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#f5f2f0}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#708090}.token.punctuation{color:#999}.token.namespace{opacity:.7}.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color:#905}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#690}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color:#9a6e3a;background:hsla(0,0%,100%,.5)}.token.atrule,.token.attr-value,.token.keyword{color:#07a}.token.class-name,.token.function{color:#dd4a68}.token.important,.token.regex,.token.variable{color:#e90}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help} \ No newline at end of file diff --git a/benchmark/template/prism.min.js b/benchmark/template/prism.min.js deleted file mode 100644 index 9183d9e..0000000 --- a/benchmark/template/prism.min.js +++ /dev/null @@ -1,6 +0,0 @@ -/* PrismJS 1.20.0 -https://prismjs.com/download.html#themes=prism&languages=clike+c+cpp */ -var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(u){var c=/\blang(?:uage)?-([\w-]+)\b/i,n=0,M={manual:u.Prism&&u.Prism.manual,disableWorkerMessageHandler:u.Prism&&u.Prism.disableWorkerMessageHandler,util:{encode:function e(n){return n instanceof W?new W(n.type,e(n.content),n.alias):Array.isArray(n)?n.map(e):n.replace(/&/g,"&").replace(/=l.reach);k+=y.value.length,y=y.next){var b=y.value;if(t.length>n.length)return;if(!(b instanceof W)){var x=1;if(h&&y!=t.tail.prev){m.lastIndex=k;var w=m.exec(n);if(!w)break;var A=w.index+(f&&w[1]?w[1].length:0),P=w.index+w[0].length,S=k;for(S+=y.value.length;S<=A;)y=y.next,S+=y.value.length;if(S-=y.value.length,k=S,y.value instanceof W)continue;for(var E=y;E!==t.tail&&(Sl.reach&&(l.reach=j);var C=y.prev;L&&(C=I(t,C,L),k+=L.length),z(t,C,x);var _=new W(o,g?M.tokenize(O,g):O,v,O);y=I(t,C,_),N&&I(t,y,N),1"+a.content+""},!u.document)return u.addEventListener&&(M.disableWorkerMessageHandler||u.addEventListener("message",function(e){var n=JSON.parse(e.data),t=n.language,r=n.code,a=n.immediateClose;u.postMessage(M.highlight(r,M.languages[t],t)),a&&u.close()},!1)),M;var e=M.util.currentScript();function t(){M.manual||M.highlightAll()}if(e&&(M.filename=e.src,e.hasAttribute("data-manual")&&(M.manual=!0)),!M.manual){var r=document.readyState;"loading"===r||"interactive"===r&&e&&e.defer?document.addEventListener("DOMContentLoaded",t):window.requestAnimationFrame?window.requestAnimationFrame(t):window.setTimeout(t,16)}return M}(_self);"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism); -Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|interface|extends|implements|trait|instanceof|new)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,boolean:/\b(?:true|false)\b/,function:/\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/}; -Prism.languages.c=Prism.languages.extend("clike",{comment:{pattern:/\/\/(?:[^\r\n\\]|\\(?:\r\n?|\n|(?![\r\n])))*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},"class-name":{pattern:/(\b(?:enum|struct)\s+(?:__attribute__\s*\(\([\s\S]*?\)\)\s*)?)\w+/,lookbehind:!0},keyword:/\b(?:__attribute__|_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while)\b/,function:/[a-z_]\w*(?=\s*\()/i,operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/,number:/(?:\b0x(?:[\da-f]+\.?[\da-f]*|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?)[ful]*/i}),Prism.languages.insertBefore("c","string",{macro:{pattern:/(^\s*)#\s*[a-z]+(?:[^\r\n\\/]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,greedy:!0,alias:"property",inside:{string:[{pattern:/^(#\s*include\s*)<[^>]+>/,lookbehind:!0},Prism.languages.c.string],comment:Prism.languages.c.comment,directive:{pattern:/^(#\s*)[a-z]+/,lookbehind:!0,alias:"keyword"},"directive-hash":/^#/,punctuation:/##|\\(?=[\r\n])/,expression:{pattern:/\S[\s\S]*/,inside:Prism.languages.c}}},constant:/\b(?:__FILE__|__LINE__|__DATE__|__TIME__|__TIMESTAMP__|__func__|EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|stdin|stdout|stderr)\b/}),delete Prism.languages.c.boolean; -!function(e){var t=/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char8_t|char16_t|char32_t|class|compl|concept|const|consteval|constexpr|constinit|const_cast|continue|co_await|co_return|co_yield|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|float|for|friend|goto|if|inline|int|int8_t|int16_t|int32_t|int64_t|uint8_t|uint16_t|uint32_t|uint64_t|long|mutable|namespace|new|noexcept|nullptr|operator|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/;e.languages.cpp=e.languages.extend("c",{"class-name":[{pattern:RegExp("(\\b(?:class|concept|enum|struct|typename)\\s+)(?!)\\w+".replace(//g,function(){return t.source})),lookbehind:!0},/\b[A-Z]\w*(?=\s*::\s*\w+\s*\()/,/\b[A-Z_]\w*(?=\s*::\s*~\w+\s*\()/i,/\w+(?=\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>\s*::\s*\w+\s*\()/],keyword:t,number:{pattern:/(?:\b0b[01']+|\b0x(?:[\da-f']+\.?[\da-f']*|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+\.?[\d']*|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]*/i,greedy:!0},operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,boolean:/\b(?:true|false)\b/}),e.languages.insertBefore("cpp","string",{"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}),e.languages.insertBefore("cpp","class-name",{"base-clause":{pattern:/(\b(?:class|struct)\s+\w+\s*:\s*)(?:[^;{}"'])+?(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:e.languages.extend("cpp",{})}}),e.languages.insertBefore("inside","operator",{"class-name":/\b[a-z_]\w*\b(?!\s*::)/i},e.languages.cpp["base-clause"])}(Prism); diff --git a/benchmark/template/report.html.in b/benchmark/template/report.html.in deleted file mode 100644 index 70181e5..0000000 --- a/benchmark/template/report.html.in +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - -
    - -
    - - Source code: -
    -    
    -@SOURCE_CODE@
    -    
    -    
    - -

    Instantiations: @INSTANTIATIONS@

    - - - - diff --git a/cmake/option_str.cmake b/cmake/option_str.cmake deleted file mode 100644 index e7226f9..0000000 --- a/cmake/option_str.cmake +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright Agustin K-ballo Berge, Fusion Fenix 2020 -# -# Distributed under the Boost Software License, Version 1.0. (See accompanying -# file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -# Provide an option that the user can optionally select. -# -# option_str( "" ...) -# -# Provides an option for the user to select. If is already set as a -# normal or cache variable, then the command does nothing (see policy CMP0077). -function(option_str variable helpstring) - set(_value ${ARGN}) - - # see if a cache variable with this name already exists - if (DEFINED CACHE{${variable}}) - # if so just make sure the doc state is correct - get_property(_type CACHE ${variable} PROPERTY TYPE) - if (NOT _type STREQUAL "UNINITIALIZED") - set_property(CACHE ${variable} PROPERTY HELPSTRING "${helpstring}") - endif() - return() - endif() - - # see if a local variable with this name already exists - if (DEFINED ${variable}) - cmake_policy(GET CMP0077 _policy_status) - if (_policy_status STREQUAL "NEW") - # if so we ignore the option_str command - return() - else() - message(AUTHOR_WARNING - "Policy CMP0077 is not set: option() honors normal variables. " - "Run \"cmake --help-policy CMP0077\" for policy details. " - "Use the cmake_policy command to set the policy and suppress this warning.\n" - "For compatibility with older versions of CMake, option_str is clearing " - "the normal variable '${variable}'.") - unset(${variable} PARENT_SCOPE) - endif() - endif() - - # nothing in the cache so add it - set(${variable} "${_value}" CACHE STRING "${helpstring}") -endfunction() diff --git a/css/img/bgcode.png b/css/img/bgcode.png new file mode 100644 index 0000000..c8cbf93 Binary files /dev/null and b/css/img/bgcode.png differ diff --git a/css/img/favicon.png b/css/img/favicon.png new file mode 100644 index 0000000..5c322e8 Binary files /dev/null and b/css/img/favicon.png differ diff --git a/css/img/home.png b/css/img/home.png new file mode 100644 index 0000000..5584aac Binary files /dev/null and b/css/img/home.png differ diff --git a/css/img/next.png b/css/img/next.png new file mode 100644 index 0000000..59800b4 Binary files /dev/null and b/css/img/next.png differ diff --git a/css/img/prev.png b/css/img/prev.png new file mode 100644 index 0000000..d88a40f Binary files /dev/null and b/css/img/prev.png differ diff --git a/css/main.css b/css/main.css new file mode 100644 index 0000000..783f5bb --- /dev/null +++ b/css/main.css @@ -0,0 +1,279 @@ +@import url(https://fonts.googleapis.com/css?family=Muli:400,300); +@import url(https://fonts.googleapis.com/css?family=Share:400,700); + +/* ============================== */ +/* BODY */ +/* ============================== */ + +body { + font-family: 'Muli',arial,sans-serif; + background-color: #FEFEFE; + margin: 0; + padding: 0; + font-size: 0.875em; + color: #616161; +} + +h1, h2, h3, h4, h5, h6 { + margin-bottom: 0.5em; + font-family: 'Share'; +} + +.title { + border-bottom: solid 2px #f5aa10; +} + +#container { + margin: 0 auto; + width: 60%; + min-width: 640px; + overflow: auto; +} + +#main { + width: 100%; +} + +a { + color: #3C6EB4; + cursor: pointer; + text-decoration: none; +} + + a:hover { + text-decoration: underline; + } + +post header.post { + margin-bottom: 10px; +} + + post header.post h1.title { + font-weight: bold; + margin: 0; + } + + post header.post h1.title a { + color: inherit; + text-decoration: none; + } + + post header.post div.date { + font-size: 0.9em; + font-weight: bold; + text-align: right; + text-transform: uppercase; + color: #999; + } + +post .body { + font-size: 1.2em; +} + +post img:not(.captcha) { + max-width: 100%; +} + +blockquote { + font-size: 1em; + width: 80%; + margin-left: 2em; + padding-left: 0.5em; + border-left: 2px solid #C3C3C3; +} + +/* ============================== */ +/* HEADER */ +/* ============================== */ +#head { + overflow: auto; + margin: 40px 0; +} + + #head div.top { + font-size: 2.4em; + margin-right: 80px; + } + + #head div.bottom { + height: 38px; + margin-right: 80px; + } + + #head .logo { + vertical-align: bottom; + } + + #head a.name { + text-decoration: none; + color: #555; + font-weight: bold; + overflow: auto; + } + + #head span.slogan { + color: #CCC; + } + +/* ============================== */ +/* HEADER POST */ +/* ============================== */ +#head_post { + overflow: auto; + margin: 10px 0; + text-align: center; +} + + #head_post a.name { + text-decoration: none; + color: #555; + font-size: 0.9em; + } + + #head_post span.slogan { + color: #CCC; + } + +/* ============================== */ +/* FOOTER */ +/* ============================== */ +#foot { + text-align: right; + font-size: 0.9em; +} + +/* ============================== */ +/* PAGER */ +/* ============================== */ +#pager { + overflow: auto; +} + + #pager a.newer { + float: right; + } + + #pager a.older { + float: left; + } + +pre, code { + font-family: monospace; + font-size: 1em; +} + +/* ============================== */ +/* BUTTONS */ +/* ============================== */ +.button, form input[type="submit"] { + font-family: 'Share'; + font-size: 12px; + background: #eee; + padding: 5px 20px; + margin: 5px 0; + overflow: hidden; + border: solid 1px #ccc; + color: #2a2a2a; + text-decoration: none; + display: inline-block; + -webkit-text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.9); + -moz-text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.9); + text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.9); + -webkit-transition-duration: 0.3s; + -moz-transition-duration: 0.3s; + transition-duration: 0.3s; +} + + .button:hover, form input[type="submit"]:hover { + text-decoration: none; + background: #f5aa10; + color: #fff; + border-color: #666; + -webkit-text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.9); + -moz-text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.9); + text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.8); + -webkit-transition: 0.2s; + -moz-transition: 0.2s; + transition: 0.2s; + } + +/* ============================== */ +/* TABLES */ +/* ============================== */ +table { + border: 1px solid #999; +} + + table th, table td { + background: #f4f4f4; + padding: 5px 15px; + } + + table thead { + border-bottom: 1px solid #999; + } + + table th { + font-weight: bold; + background: #eaeaea; + } + + table td, table th { + border-right: 1px solid #999; + } + +pre.code { + -moz-border-radius: 0 0 0 0 !important; + -webkit-border-radius: 0 0 0 0 !important; + background-color: #F4F4F4 !important; + border: 1px dashed #CCC; + float: none !important; + height: auto !important; + line-height: 1.1em !important; + margin: 1em 0px !important; + outline: 0 !important; + overflow: visible !important; + padding: 1em; + position: static !important; + text-align: left !important; + vertical-align: baseline !important; + width: 100% !important; + box-sizing: content-box !important; + font-family: monospace !important; + font-weight: normal !important; + font-style: normal !important; + font-size: 1em !important; + min-height: inherit !important; + box-sizing: border-box !important; +} + +/* ============================== */ +/* NAVIGATION */ +/* ============================== */ +.nav { + text-align: right; +} + + .nav a { + color: white; + padding-left: 0.5em; + } + + .nav img { + border-width: 0px; + } + +/* ============================== */ +/* REFERENCE */ +/* ============================== */ +.reference ul { + list-style: none; +} + + .reference ul li { + margin: 14px 0; + } + + .reference ul li ul { + list-style: disc; + } diff --git a/css/normalize.css b/css/normalize.css new file mode 100644 index 0000000..3f7f6f2 --- /dev/null +++ b/css/normalize.css @@ -0,0 +1,35 @@ +/*! normalize.css v2.0.1 | MIT License | git.io/normalize */ +article,aside,details,figcaption,figure,footer,header,hgroup,nav,section,summary{display:block} +audio,canvas,video{display:inline-block} +audio:not([controls]){display:none;height:0} +[hidden]{display:none} +html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%} +a:focus{outline:thin dotted} +a:active,a:hover{outline:0} +h1{font-size:2em} +abbr[title]{border-bottom:1px dotted} +b,strong{font-weight:700} +dfn{font-style:italic} +mark{background:#ff0;color:#000} +code,kbd,pre,samp{font-family:monospace, serif;font-size:1em} +pre{white-space:pre-wrap;word-wrap:break-word} +q{quotes:\201C \201D \2018 \2019} +small{font-size:80%} +sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline} +sup{top:-.5em} +sub{bottom:-.25em} +img{border:0} +svg:not(:root){overflow:hidden} +fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em} +button,input,select,textarea{font-family:inherit;font-size:100%;margin:0} +button,input{line-height:normal} +button,html input[type=button],/* 1 */ +input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer} +button[disabled],input[disabled]{cursor:default} +input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0} +input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box} +input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none} +textarea{overflow:auto;vertical-align:top} +table{border-collapse:collapse;border-spacing:0} +body,figure{margin:0} +legend,button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0} \ No newline at end of file diff --git a/benchmark/template/nv.d3.min.css b/css/nv.d3.min.css similarity index 100% rename from benchmark/template/nv.d3.min.css rename to css/nv.d3.min.css diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt deleted file mode 100644 index a261a6b..0000000 --- a/example/CMakeLists.txt +++ /dev/null @@ -1,56 +0,0 @@ -# Eggs.Invoke -# -# Copyright Agustin K-ballo Berge, Fusion Fenix 2017-2020 -# -# Distributed under the Boost Software License, Version 1.0. (See accompanying -# file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -cmake_minimum_required(VERSION 3.0...3.18) - -project(Eggs.Invoke_Example CXX) - -if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) - set(Eggs.Invoke_SOURCE_DIR "" CACHE PATH "Path to Eggs.Invoke source root") - - if (Eggs.Invoke_SOURCE_DIR) - message(STATUS "Embedding Eggs.Invoke via add_subdirectory") - if (NOT EXISTS ${Eggs.Invoke_SOURCE_DIR}/CMakeLists.txt) - message(FATAL_ERROR "Given path to Eggs.Invoke is invalid") - endif() - add_subdirectory(${Eggs.Invoke_SOURCE_DIR} eggs.invoke) - else() - if (DEFINED Eggs.Invoke_DIR) - find_package(Eggs.Invoke CONFIG REQUIRED) - else() - find_package(Eggs.Invoke CONFIG) - endif() - - if (Eggs.Invoke_FOUND) - message(STATUS "Using Eggs.Invoke via config package file") - else() - include(FetchContent OPTIONAL RESULT_VARIABLE FetchContent_FOUND) - if (NOT FetchContent_FOUND) # CMake 3.10 or older - message(FATAL_ERROR "Eggs.Invoke not found and FetchContent not available") - endif() - - message(STATUS "Embedding Eggs.Invoke via FetchContent") - FetchContent_Declare(eggs.invoke - GIT_REPOSITORY https://github.com/eggs-cpp/invoke.git) - if (COMMAND FetchContent_MakeAvailable) # CMake 3.14 or newer - message(VERBOSE " using FetchContent_MakeAvailable") - FetchContent_MakeAvailable(eggs.invoke) - else() - message(VERBOSE " using FetchContent_Populate") - FetchContent_GetProperties(eggs.invoke) - if (NOT eggs.invoke_POPULATED) - FetchContent_Populate(eggs.invoke) - add_subdirectory(${eggs.invoke_SOURCE_DIR} ${eggs.invoke_BINARY_DIR}) - endif() - endif() - endif() - endif() -endif() - -add_executable(example example.cpp) -target_link_libraries(example Eggs::Invoke) -set_property(TARGET example PROPERTY FOLDER "example") diff --git a/example/README.md b/example/README.md deleted file mode 100644 index 97f7d7f..0000000 --- a/example/README.md +++ /dev/null @@ -1,66 +0,0 @@ -**Eggs.Invoke** -================== - -## Example ## - -This directory contains an example of use of **Eggs.Invoke**. - -## Build - -Execute the following commands from the `example` directory: - -```bash -mkdir build && cd build -cmake .. -cmake --build . -``` - -When building the example cmake project as standalone, it will attempt to -locate **Eggs.Invoke** in a number of ways: - -#### The `add_subdirectory` way - -```cmake -add_subdirectory(${Eggs.Invoke_SOURCE_DIR} eggs.invoke) -``` - -If `Eggs.Invoke_SOURCE_DIR` is defined, embeds the project at the given path -as a subproject of the example. - -[_Note_: the second argument is the corresponding binary directory, and it is -required when the source directory is absolute]. - -#### The `find_package` way - -```cmake -find_package(Eggs.Invoke CONFIG) -``` - -Looks for the cmake package config file `eggs.invoke-config.cmake`, deployed -during installation of the library. - -If the library has not been installed to a well-known system location, add the -installation prefix of the library to `CMAKE_PREFIX_PATH` or set -`Eggs.Invoke_DIR` to the directory containing `eggs.invoke-config.cmake`. - -[_Note_: use argument `REQUIRED` for stopping the configuration process when -the package is not found]. - -#### The `FetchContent` way - -```cmake -include(FetchContent) -FetchContent_Declare(eggs.invoke - GIT_REPOSITORY https://github.com/eggs-cpp/invoke.git) -FetchContent_MakeAvailable(eggs.invoke) -``` - -Downloads the sources from github, then embeds the project as a subproject of -the example (as if by `add_subdirectory`). - ---- - -> Copyright _Agustín Bergé_, _Fusion Fenix_ 2017-2020 -> -> Distributed under the Boost Software License, Version 1.0. (See accompanying -> file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/example/example.cpp b/example/example.cpp deleted file mode 100644 index b523722..0000000 --- a/example/example.cpp +++ /dev/null @@ -1,115 +0,0 @@ -// Eggs.Invoke -// -// Copyright Agustin K-ballo Berge, Fusion Fenix 2020 -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#include - -#include -#include -#include -#include - -/// identity function -struct identity -{ - template - constexpr T&& operator()(T&& t) const noexcept - { - return std::forward(t); - } -}; - -/// algorithm that prints to `std::cout` the projection of those elements in -/// the range [iter, sentinel) that satisfy a given predicate -template -void print_if(Iter iter, Sentinel sentinel, Pred const& pred, Proj const& proj = {}) -{ - /// Check that `INVOKE(pred, *iter)` is well-formed, - static_assert(eggs::is_invocable::value, - "Predicate shall accept the iterator's value type as its only argument"); - - /// and that it returns something convertible to `bool`; - static_assert(std::is_convertible< - eggs::invoke_result_t, bool>::value, - "Predicate return type shall be convertible to bool"); - - /// ...or check both requirements at once: - /// Check that `INVOKE(pred, *iter)` is well-formed. - static_assert(eggs::is_invocable_r::value, - "Predicate shall accept the iterator's value type as its only argument, " - "and its return type shall be convertible to bool"); - - /// Also check that `INVOKE(proj, *iter)` is well-formed, - static_assert(eggs::is_invocable::value, - "Projection shall accept the iterator's value type as its only argument"); - -#if __cpp_generic_lambdas - /// and that it returns something "printable" to `std::cout`. - auto printable = [](auto const& v) -> decltype((void)(std::cout << v)) {}; - static_assert(eggs::is_invocable>::value, - "Projection return type shall be printable to std::cout"); -#endif - - for (; iter != sentinel; ++iter) - { - if (eggs::invoke(pred, *iter)) // or eggs::invoke_r(pred, *iter) - std::cout << eggs::invoke(proj, *iter) << '\n'; - } -} - -/// user definition -struct User -{ - std::string name; - - bool is_superuser; - - constexpr bool is_regular_user() const noexcept { return !is_superuser; } - - friend std::ostream& operator<<(std::ostream& out, User const& user) - { - return out << '(' - << "name: " << user.name - << ", is_superuser: " << user.is_superuser - << ')'; - } -}; - -/// table of users -std::vector const users = { - { "Alice", true }, - { "Bob", false }, - { "Charlie", false } -}; - -int main() -{ - /// print all users - /// - /// `eggs::invoke(, user)` is equivalent to `(user)`. - std::cout << "Users:\n"; - print_if(users.begin(), users.end(), [](User const&) { return true; }); - std::cout << '\n'; - - /// print the names of superusers - /// - /// `eggs::invoke(&User::is_superuser, user)` is equivalent to - /// `user.is_superuser` or `user->is_superuser`. - std::cout << "Superusers:\n"; - print_if(users.begin(), users.end(), &User::is_superuser, &User::name); - std::cout << '\n'; - - /// print the names of regular users - /// - /// `eggs::invoke(&User::is_regular_user, user)` is equivalent to - /// `user.is_regular_user()` or `user->is_regular_user()`. - std::cout << "Regular users:\n"; - print_if(users.begin(), users.end(), &User::is_regular_user, &User::name); - std::cout << '\n'; - - return 0; -} diff --git a/include/eggs/invoke.hpp b/include/eggs/invoke.hpp deleted file mode 100644 index 7f93cad..0000000 --- a/include/eggs/invoke.hpp +++ /dev/null @@ -1,473 +0,0 @@ -//! \file eggs/invoke.hpp -// Eggs.Invoke -// -// Copyright Agustin K-ballo Berge, Fusion Fenix 2017-2020 -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#ifndef EGGS_INVOKE_HPP -#define EGGS_INVOKE_HPP - -#include -#include -#include - -namespace eggs { namespace detail -{ -#define EGGS_FWD(...) static_cast(__VA_ARGS__) - - /////////////////////////////////////////////////////////////////////////// - template ::value> - struct invoke_mem_ptr; - - // when `pm` is a pointer to member of a class `C` and - // `is_base_of_v>` is `true`; - template - struct invoke_mem_ptr - { - T C::*pm; - -#if !__cpp_aggregate_paren_init - constexpr invoke_mem_ptr(T C::*pm) noexcept - : pm(pm) - {} -#endif - - template - constexpr auto operator()(T1&& t1) const - noexcept(noexcept(EGGS_FWD(t1).*pm)) - -> decltype(EGGS_FWD(t1).*pm) - { - return EGGS_FWD(t1).*pm; - } - }; - - template - struct invoke_mem_ptr - { - T C::*pm; - -#if !__cpp_aggregate_paren_init - constexpr invoke_mem_ptr(T C::*pm) noexcept - : pm(pm) - {} -#endif - - template - constexpr auto operator()(T1&& t1, Tn&&... tn) const - noexcept(noexcept((EGGS_FWD(t1).*pm)(EGGS_FWD(tn)...))) - -> decltype((EGGS_FWD(t1).*pm)(EGGS_FWD(tn)...)) - { - return (EGGS_FWD(t1).*pm)(EGGS_FWD(tn)...); - } - }; - - // when `pm` is a pointer to member of a class `C` and - // `remove_cvref_t` is a specialization of `reference_wrapper`; - template - struct invoke_mem_ptr - { - T C::*pm; - -#if !__cpp_aggregate_paren_init - constexpr invoke_mem_ptr(T C::*pm) noexcept - : pm(pm) - {} -#endif - - template - constexpr auto operator()(T1&& t1) const - noexcept(noexcept(t1.get().*pm)) - -> decltype(t1.get().*pm) - { - return t1.get().*pm; - } - }; - - template - struct invoke_mem_ptr - { - T C::*pm; - -#if !__cpp_aggregate_paren_init - constexpr invoke_mem_ptr(T C::*pm) noexcept - : pm(pm) - {} -#endif - - template - constexpr auto operator()(T1&& t1, Tn&&... tn) const - noexcept(noexcept((t1.get().*pm)(EGGS_FWD(tn)...))) - -> decltype((t1.get().*pm)(EGGS_FWD(tn)...)) - { - return (t1.get().*pm)(EGGS_FWD(tn)...); - } - }; - - // when `pm` is a pointer to member of a class `C` and `T` does not - // satisfy the previous two items; - template - struct invoke_mem_ptr - { - T C::*pm; - -#if !__cpp_aggregate_paren_init - constexpr invoke_mem_ptr(T C::*pm) noexcept - : pm(pm) - {} -#endif - - template - constexpr auto operator()(T1&& t1) const - noexcept(noexcept((*EGGS_FWD(t1)).*pm)) - -> decltype((*EGGS_FWD(t1)).*pm) - { - return (*EGGS_FWD(t1)).*pm; - } - }; - - template - struct invoke_mem_ptr - { - T C::*pm; - -#if !__cpp_aggregate_paren_init - constexpr invoke_mem_ptr(T C::*pm) noexcept - : pm(pm) - {} -#endif - - template - constexpr auto operator()(T1&& t1, Tn&&... tn) const - noexcept(noexcept(((*EGGS_FWD(t1)).*pm)(EGGS_FWD(tn)...))) - -> decltype(((*EGGS_FWD(t1)).*pm)(EGGS_FWD(tn)...)) - { - return ((*EGGS_FWD(t1)).*pm)(EGGS_FWD(tn)...); - } - }; - - /////////////////////////////////////////////////////////////////////////// - template - auto invoke(F&&, ...) - -> F&&; - - template - auto invoke(T C::*, T1 const&, ...) - -> invoke_mem_ptr::value, - /*RefWrapper=*/false>; - - template - auto invoke(T C::*, std::reference_wrapper, ...) - -> invoke_mem_ptr; - - //! EGGS_INVOKE(F, ...) - //! - //! - _Returns_: `INVOKE(F __VA_OPT__(,) __VA_ARGS__)`. -#if __cplusplus > 201703L // C++20: P0306 -#define EGGS_INVOKE(F, ...) \ - (static_cast(F)(__VA_ARGS__)) -#elif _MSVC_TRADITIONAL -#define EGGS_INVOKE(F, ...) \ - (static_cast(F)(__VA_ARGS__)) -#else -#define EGGS_INVOKE(F, ...) \ - (static_cast(F)(__VA_ARGS__)) -#endif - - /////////////////////////////////////////////////////////////////////////// - // `INVOKE(f, t1, t2, ..., tN)` implicitly converted to `R`. - template ::type> - struct invoke_r - { - private: - static R conversion(R) noexcept; - - public: - template - static constexpr auto call(F&& f, Args&&... args) - noexcept(noexcept(conversion( - EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...)))) - -> decltype(conversion( - EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...))) - { - return EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...); - } - }; - - // `static_cast(INVOKE(f, t1, t2, ..., tN))` if `R` is _cv_ `void`. - template - struct invoke_r - { - template - static constexpr auto call(F&& f, Args&&... args) - noexcept(noexcept( - EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...))) - -> decltype(static_cast( - EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...))) - { - return static_cast( - EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...)); - } - }; - - //! EGGS_INVOKE(R, F, ...) - //! - //! - _Returns_: `INVOKE(F __VA_OPT__(,) __VA_ARGS__)`. -#define EGGS_INVOKE_R(R, ...) \ - (::eggs::detail::invoke_r::call(__VA_ARGS__)) - -}} // namespace eggs::detail - -namespace eggs -{ - /////////////////////////////////////////////////////////////////////////// - namespace detail - { - template - struct invoke_result_impl - {}; - - template - struct invoke_result_impl(), std::declval()...))> - { - using type = decltype( - EGGS_INVOKE(std::declval(), std::declval()...)); - }; - } // namespace detail - - //! template struct invoke_result; - //! - //! - _Comments_: If the expression `INVOKE(std::declval(), - //! std::declval()...)` is well-formed when treated as an - //! unevaluated operand, the member typedef `type` names the type - //! `decltype(INVOKE(std::declval(), std::declval()...))`; - //! otherwise, there shall be no member `type`. Access checking is - //! performed as if in a context unrelated to `Fn` and `ArgTypes`. Only - //! the validity of the immediate context of the expression is considered. - //! - //! - _Preconditions_: `Fn` and all types in the template parameter pack - //! `ArgTypes` are complete types, _cv_ `void`, or arrays of unknown - //! bound. - template - struct invoke_result - : detail::invoke_result_impl - {}; - - //! template - //! using invoke_result_t = typename invoke_result::type; - template - using invoke_result_t = - typename invoke_result::type; - - /////////////////////////////////////////////////////////////////////////// - namespace detail - { - template - struct is_invocable_impl - : std::false_type - {}; - - template - struct is_invocable_impl(), std::declval()...))> - : std::true_type - {}; - } - - //! template struct is_invocable; - //! - //! - _Condition_: The expression `INVOKE(std::declval(), - //! std::declval()...)` is well-formed when treated as an - //! unevaluated operand. - //! - //! - _Comments_: `Fn` and all types in the template parameter pack - //! `ArgTypes` shall be complete types, _cv_ `void`, or arrays of - //! unknown bound. - template - struct is_invocable - : detail::is_invocable_impl::type - {}; - -#if __cpp_variable_templates - //! template // (C++14) - //! inline constexpr bool is_invocable_v = - //! eggs::is_invocable::value; - template -#if __cpp_inline_variables - inline -#endif - constexpr bool is_invocable_v = - is_invocable::value; -#endif - - /////////////////////////////////////////////////////////////////////////// - namespace detail - { - template - struct is_invocable_r_impl - : std::false_type - {}; - - template - struct is_invocable_r_impl(), std::declval()...))> - : std::true_type - {}; - } - - //! template struct is_invocable_r; - //! - //! - _Condition_: The expression `INVOKE(std::declval(), - //! std::declval()...)` is well-formed when treated as an - //! unevaluated operand. - //! - //! - _Comments_: `Fn`, `R`, and all types in the template parameter pack - //! `ArgTypes` shall be complete types, _cv_ `void`, or arrays of - //! unknown bound. - template - struct is_invocable_r - : detail::is_invocable_r_impl::type - {}; - -#if __cpp_variable_templates - //! template // (C++14) - //! inline constexpr bool is_invocable_r_v = - //! eggs::is_invocable_r::value; - template -#if __cpp_inline_variables - inline -#endif - constexpr bool is_invocable_r_v = - is_invocable_r::value; -#endif - - /////////////////////////////////////////////////////////////////////////// - namespace detail - { - template - struct is_nothrow_invocable_impl - : std::false_type - {}; - - template - struct is_nothrow_invocable_impl(), std::declval()...))> - : std::integral_constant(), std::declval()...))> - {}; - } - - //! template struct is_nothrow_invocable; - //! - //! - _Condition_: `eggs::is_invocable_v` is `true` and - //! the expression `INVOKE(std::declval(), std::declval()...)` - //! is known not to throw any exceptions. - //! - //! - _Comments_: `Fn` and all types in the template parameter pack - //! `ArgTypes` shall be complete types, _cv_ `void`, or arrays of - //! unknown bound. - template - struct is_nothrow_invocable - : detail::is_nothrow_invocable_impl::type - {}; - -#if __cpp_variable_templates - //! template // (C++14) - //! inline constexpr bool is_nothrow_invocable_v = - //! eggs::is_nothrow_invocable::value; - template -#if __cpp_inline_variables - inline -#endif - constexpr bool is_nothrow_invocable_v = - is_nothrow_invocable::value; -#endif - - /////////////////////////////////////////////////////////////////////////// - namespace detail - { - template - struct is_nothrow_invocable_r_impl - : std::false_type - {}; - - template - struct is_nothrow_invocable_r_impl(), std::declval()...))> - : std::integral_constant(), std::declval()...))> - {}; - } - - //! template struct is_nothrow_invocable_r; - //! - //! - _Condition_: `eggs::is_invocable_r_v` is `true` - //! and the expression `INVOKE(std::declval(), std::declval()...)` - //! is known not to throw any exceptions. - //! - //! - _Comments_: `Fn`, `R`, and all types in the template parameter pack - //! `ArgTypes` shall be complete types, _cv_ `void`, or arrays of - //! unknown bound. - template - struct is_nothrow_invocable_r - : detail::is_nothrow_invocable_r_impl::type - {}; - -#if __cpp_variable_templates - //! template // (C++14) - //! inline constexpr bool is_nothrow_invocable_r_v = - //! eggs::is_nothrow_invocable_r::value; - template -#if __cpp_inline_variables - inline -#endif - constexpr bool is_nothrow_invocable_r_v = - is_nothrow_invocable_r::value; -#endif - - /////////////////////////////////////////////////////////////////////////// - //! template - //! constexpr eggs::invoke_result_t invoke(F&& f, Args&&... args) - //! noexcept(eggs::is_nothrow_invocable_v); - //! - //! - _Returns_: `INVOKE(std::forward(f), std::forward(args)...)`. - //! - //! - _Remarks_: This function shall not participate in overload resolution - //! unless `eggs::is_invocable_v` is `true`. - template - constexpr auto - invoke(Fn&& f, ArgTypes&&... args) - noexcept(noexcept(EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...))) - -> decltype(EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...)) - { - return EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...); - } - - /////////////////////////////////////////////////////////////////////////// - //! template // (extension) - //! constexpr R eggs::invoke_r(F&& f, Args&&... args) - //! noexcept(eggs::is_nothrow_invocable_r_v); - //! - //! - _Returns_: `INVOKE(std::forward(f), std::forward(args)...)`. - //! - //! - _Remarks_: This function shall not participate in overload resolution - //! unless `eggs::is_invocable_r_v` is `true`. - template - constexpr auto - invoke_r(Fn&& f, ArgTypes&&... args) - noexcept(noexcept(EGGS_INVOKE_R(R, EGGS_FWD(f), EGGS_FWD(args)...))) - -> decltype(EGGS_INVOKE_R(R, EGGS_FWD(f), EGGS_FWD(args)...)) - { - return EGGS_INVOKE_R(R, EGGS_FWD(f), EGGS_FWD(args)...); - } - -#undef EGGS_FWD -} // namespace eggs - -#endif /*EGGS_INVOKE_HPP*/ diff --git a/index.html b/index.html new file mode 100644 index 0000000..d54a759 --- /dev/null +++ b/index.html @@ -0,0 +1,71 @@ + + + + + + + Eggs.Invoke + + + + + + + + + + + + +
    + + +
    +

    Eggs.Invoke is a C++11/14/17/20 single-header implementation of `INVOKE` and its related facilities. —see it on Github—.

    +
    + + +
    +
    + +

    Requirements

    +
    +

    The library requires a standard conformant implementation of C++11; a few additional features are only available under C++14. There are no external dependencies.

    +
    +
    + +
    +

    + Copyright + Agustín Bergé, + Fusion Fenix 2017-2020 +

    + +

    + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +

    +
    + + diff --git a/benchmark/template/d3.min.js b/js/d3.min.js similarity index 100% rename from benchmark/template/d3.min.js rename to js/d3.min.js diff --git a/js/jsrender.min.js b/js/jsrender.min.js new file mode 100644 index 0000000..b4bc5ac --- /dev/null +++ b/js/jsrender.min.js @@ -0,0 +1,4 @@ +/*! JsRender v1.0.7: http://jsviews.com/#jsrender */ +/*! **VERSION FOR WEB** (For NODE.JS see http://jsviews.com/download/jsrender-node.js) */ +!function(t,e){var n=e.jQuery;"object"==typeof exports?module.exports=n?t(e,n):function(n){if(n&&!n.fn)throw"Provide jQuery or null";return t(e,n)}:"function"==typeof define&&define.amd?define(function(){return t(e)}):t(e,!1)}(function(t,e){"use strict";function n(t,e){return function(){var n,r=this,i=r.base;return r.base=t,n=e.apply(r,arguments),r.base=i,n}}function r(t,e){return st(e)&&(e=n(t?t._d?t:n(a,t):a,e),e._d=(t&&t._d||0)+1),e}function i(t,e){var n,i=e.props;for(n in i)!Vt.test(n)||t[n]&&t[n].fix||(t[n]="convert"!==n?r(t.constructor.prototype[n],i[n]):i[n])}function o(t){return t}function a(){return""}function s(t){try{throw console.log("JsRender dbg breakpoint: "+t),"dbg breakpoint"}catch(e){}return this.base?this.baseApply(arguments):t}function l(t){this.name=(e.link?"JsViews":"JsRender")+" Error",this.message=t||this.name}function d(t,e){if(t){for(var n in e)t[n]=e[n];return t}}function c(t,e,n){return t?lt(t)?c.apply(ot,t):(wt=n?n[0]:wt,/^(\W|_){5}$/.test(t+e+wt)||S("Invalid delimiters"),mt=t[0],_t=t[1],xt=e[0],bt=e[1],gt.delimiters=[mt+_t,xt+bt,wt],t="\\"+mt+"(\\"+wt+")?\\"+_t,e="\\"+xt+"\\"+bt,rt="(?:(\\w+(?=[\\/\\s\\"+xt+"]))|(\\w+)?(:)|(>)|(\\*))\\s*((?:[^\\"+xt+"]|\\"+xt+"(?!\\"+bt+"))*?)",ft.rTag="(?:"+rt+")",rt=new RegExp("(?:"+t+rt+"(\\/)?|\\"+mt+"(\\"+wt+")?\\"+_t+"(?:(?:\\/(\\w+))\\s*|!--[\\s\\S]*?--))"+e,"g"),ft.rTmpl=new RegExp("^\\s|\\s$|<.*>|([^\\\\]|^)[{}]|"+t+".*"+e),ht):gt.delimiters}function p(t,e){e||t===!0||(e=t,t=void 0);var n,r,i,o,a=this,s="root"===e;if(t){if(o=e&&a.type===e&&a,!o)if(n=a.views,a._.useKey){for(r in n)if(o=e?n[r].get(t,e):n[r])break}else for(r=0,i=n.length;!o&&r1,v=f.ctx;if(n){if(f._||(c=f.index,f=f.tag),p=f,v&&v.hasOwnProperty(n)||(v=pt).hasOwnProperty(n)){if(s=v[n],"tag"===n||"tagCtx"===n||"root"===n||"parentTags"===n)return s}else v=void 0;if((!Ct&&f.tagCtx||f.linked)&&(s&&s._cxp||(f=f.tagCtx||st(s)?f:(f=f.scope||f,!f.isTop&&f.ctx.tag||f),void 0!==s&&f.tagCtx&&(f=f.tagCtx.view.scope),v=f._ocps,s=v&&v.hasOwnProperty(n)&&v[n]||s,s&&s._cxp||!i&&!g||((v||(f._ocps=f._ocps||{}))[n]=s=[{_ocp:s,_vw:p,_key:n}],s._cxp={path:jt,ind:0,updateValue:function(t,n){return e.observable(s[0]).setProperty(jt,t),this}})),l=s&&s._cxp)){if(arguments.length>2)return a=s[1]?ft._ceo(s[1].deps):[jt],a.unshift(s[0]),a._cxp=l,a;if(c=l.tagElse,u=s[1]?l.tag&&l.tag.cvtArgs?l.tag.cvtArgs(c,1)[l.ind]:s[1](s[0].data,s[0],ft):s[0]._ocp,g)return ft._ucp(n,r,f,l),f;s=u}return s&&st(s)&&(o=function(){return s.apply(this&&this!==t?this:p,arguments)},d(o,s)),o||s}}function h(t){return t&&(t.fn?t:this.getRsc("templates",t)||dt(t))}function m(t,e,n,r){var o,a,s,l,c,p="number"==typeof n&&e.tmpl.bnds[n-1];if(void 0===r&&p&&p._lr&&(r=""),void 0!==r?n=r={props:{},args:[r]}:p&&(n=p(e.data,e,ft)),p=p._bd&&p,t||p){if(a=e._lc,o=a&&a.tag,n.view=e,!o){if(o=d(new ft._tg,{_:{bnd:p,unlinked:!0,lt:n.lt},inline:!a,tagName:":",convert:t,onArrayChange:!0,flow:!0,tagCtx:n,tagCtxs:[n],_is:"tag"}),l=n.args.length,l>1)for(c=o.bindTo=[];l--;)c.unshift(l);a&&(a.tag=o,o.linkCtx=a),n.ctx=Q(n.ctx,(a?a.view:e).ctx),i(o,n)}o._er=r&&s,o.ctx=n.ctx||o.ctx||{},n.ctx=void 0,s=o.cvtArgs()[0],o._er=r&&s}else s=n.args[0];return s=p&&e._.onRender?e._.onRender(s,e,o):s,void 0!=s?s:""}function _(t,e){var n,r,i,o,a,s,l,d=this;if(d.tagName){if(s=d,d=(s.tagCtxs||[d])[t||0],!d)return}else s=d.tag;if(a=s.bindFrom,o=d.args,(l=s.convert)&&""+l===l&&(l="true"===l?void 0:d.view.getRsc("converters",l)||S("Unknown converter: '"+l+"'")),l&&!e&&(o=o.slice()),a){for(i=[],n=a.length;n--;)r=a[n],i.unshift(x(d,r));e&&(o=i)}if(l){if(l=l.apply(s,i||o),void 0===l)return o;if(a=a||[0],n=a.length,lt(l)&&l.length===n||(l=[l],a=[0],n=1),e)o=l;else for(;n--;)r=a[n],+r===r&&(o[r]=l[n])}return o}function x(t,e){return t=t[+e===e?"args":"props"],t&&t[e]}function b(t){return this.cvtArgs(t,1)}function w(t,e){var n,r,i=this;if(""+e===e){for(;void 0===n&&i;)r=i.tmpl&&i.tmpl[t],n=r&&r[e],i=i.parent;return n||ot[t][e]}}function y(t,e,n,r,o,a){function s(t){var e=l[t];if(void 0!==e)for(e=lt(e)?e:[e],h=e.length;h--;)q=e[h],isNaN(parseInt(q))||(e[h]=parseInt(q));return e||[0]}e=e||it;var l,d,c,p,u,f,g,h,m,w,y,C,k,j,T,A,P,F,N,R,M,$,V,I,D,q,U,K,J,L,B=0,H="",W=e._lc||!1,Z=e.ctx,z=n||e.tmpl,G="number"==typeof r&&e.tmpl.bnds[r-1];for("tag"===t._is?(l=t,t=l.tagName,r=l.tagCtxs,c=l.template):(d=e.getRsc("tags",t)||S("Unknown tag: {{"+t+"}} "),c=d.template),void 0===a&&G&&(G._lr=d.lateRender&&G._lr!==!1||G._lr)&&(a=""),void 0!==a?(H+=a,r=a=[{props:{},args:[],params:{props:{}}}]):G&&(r=G(e.data,e,ft)),g=r.length;B0&&(a=n)){if(!a)if(/^\.?\/[^\\:*?"<>]*$/.test(n))(s=dt[t=t||n])?n=s:a=document.getElementById(n);else if(e.fn&&!ft.rTmpl.test(n))try{a=e(n,document)[0]}catch(l){}a&&("SCRIPT"!==a.tagName&&S(n+": Use script block, not "+a.tagName),i?n=a.innerHTML:(o=a.getAttribute(Bt),o&&(o!==Qt?(n=dt[o],delete dt[o]):e.fn&&(n=e.data(a)[Qt])),o&&n||(t=t||(e.fn?Qt:n),n=A(t,a.innerHTML,r,i)),n.tmplName=t=t||o,t!==Qt&&(dt[t]=n),a.setAttribute(Bt,t),e.fn&&e.data(a,Qt,n))),a=void 0}else n.fn||(n=void 0);return n}var a,s,l=n=n||"";if(ft._html=ct.html,0===i&&(i=void 0,l=o(l)),i=i||(n.markup?n.bnds?d({},n):n:{}),i.tmplName=i.tmplName||t||"unnamed",r&&(i._parentTmpl=r),!l&&n.markup&&(l=o(n.markup))&&l.fn&&(l=l.markup),void 0!==l)return l.render||n.render?l.tmpls&&(s=l):(n=R(l,i),q(l.replace(Pt,"\\$&"),n)),s||(s=d(function(){return s.render.apply(s,arguments)},n),k(s)),s}function P(t,e){return st(t)?t.call(e):t}function F(t,e,n){Object.defineProperty(t,e,{value:n,configurable:!0})}function N(t,n){function r(t){c.apply(this,t)}function i(){return new r(arguments)}function o(t,e){for(var n,r,i,o,a,s=0;sY-(Q||0)){if(Q=e.trim(L.slice(Q,Y+r.length)),H=s||g[m-1].bd,W=H[H.length-1],W&&W.prm){for(;W.sb&&W.sb.prm;)W=W.sb;Z=W.sb={path:W.sb,bnd:W.bnd}}else H.push(Z={path:H.pop()});W&&W.sb===Z&&(k[m]=k[m-1].slice(W._cpPthSt)+k[m],k[m-1]=k[m-1].slice(0,W._cpPthSt)),Z._cpPthSt=C[m-1],Z._cpKey=Q,k[m]+=L.slice(j,J),j=J,Z._cpfn=Wt[Q]=Wt[Q]||new Function("data,view,j","//"+Q+"\nvar v;\nreturn ((v="+k[m]+("]"===S?")]":S)+")!=null?v:null);"),k[m-1]+=w[h]&&vt.cache?'view.getCache("'+Q.replace(Pt,"\\$&")+'"':k[m],Z.prm=f.bd,Z.bnd=Z.bnd||Z.path&&Z.path.indexOf("^")>=0}k[m]=""}"["===$&&($="[j._sq("),"["===d&&(d="[j._sq(")}return X=p?(p=!O,p?r:E+'"'):c?(c=!I,c?r:E+'"'):(d?(b[++h]=!0,_[h]=0,u&&(y[m++]=Y++,f=g[m]={bd:[]},k[m]="",C[m]=1),d):"")+(K?h?"":(v=L.slice(v,Y),(a?(a=l=s=!1,"\b"):"\b,")+v+(v=Y+r.length,u&&n.push(f.bd=[]),"\b")):N?(m&&D(t),u&&n.pop(),a="_"+A,l=T,v=Y+r.length,u&&(u=f.bd=n[a]=[],u.skp=!T),A+":"):A?A.split("^").join(".").replace(ft.rPath,B)+($||P):P?P:S?"]"===S?")]":")":V?(w[h]||D(t),","):o?"":(p=O,c=I,'"')),p||c||S&&(w[h]=!1,h--),u&&(p||c||(S&&(b[h+1]&&(f=g[--m],b[h+1]=!1),x=_[h+1]),$&&(_[h+1]=k[m].length+(d?1:0),(A||S)&&(f=g[++m]={bd:[]},b[h+1]=!0))),k[m]=(k[m]||"")+L.slice(j,J),j=J+r.length,p||c||((G=d&&b[h+1])&&(k[m-1]+=d,C[m-1]++),"("===$&&z&&!Z&&(k[m]=k[m-1].slice(x)+k[m],k[m-1]=k[m-1].slice(0,x))),k[m]+=G?X.slice(1):X),p||c||!$||(h++,A&&"("===$&&(w[h]=!0)),p||c||!U||(u&&(k[m]+=$),X+=$),X}var a,s,l,d,c,p,u=n&&n[0],f={bd:u},g={0:f},v=0,h=0,m=0,_={},x=0,b={},w={},y={},C={0:0},k={0:""},j=0;return"@"===t[0]&&(t=t.replace(Dt,".")),d=(t+(r?" ":"")).replace(ft.rPrm,o),u&&(d=k[0]),!h&&d||D(t)}function B(t,e,n){var r,i,o,a,s,l,d,c,p,u,f,g,v,h,m,_,x,b,w,y,C,k,j,T,A,P,F,N,M,$,V,E,O,I=0,S=vt.useViews||e.useViews||e.tags||e.templates||e.helpers||e.converters,q="",K={},L=t.length;for(""+e===e?(b=n?'data-link="'+e.replace(Tt," ").slice(1,-1)+'"':e,e=0):(b=e.tmplName||"unnamed",e.allowCode&&(K.allowCode=!0),e.debug&&(K.debug=!0),f=e.bnds,x=e.tmpls),r=0;r":a+o):(C&&(w=R(k,K),w.tmplName=b+"/"+o,w.useViews=w.useViews||S,B(C,w),S=w.useViews,x.push(w)),A||(y=o,S=S||o&&(!ut[o]||!ut[o].flow),T=q,q=""),j=t[r+1],j=j&&"else"===j[0]),M=N?";\ntry{\nret+=":"\n+",h="",m="",P&&(g||$||a&&a!==Jt||V)){if(F=new Function("data,view,j","// "+b+" "+ ++I+" "+o+E+"{"+s+"};"+O),F._er=N,F._tag=o,F._bd=!!g,F._lr=V,n)return F;U(F,g),_='c("'+a+'",view,',u=!0,h=_+I+",",m=")"}if(q+=P?(n?(N?"try{\n":"")+"return ":M)+(u?(u=void 0,S=p=!0,_+(F?(f[I-1]=F,I):"{"+s+"}")+")"):">"===o?(d=!0,"h("+v[0]+")"):(c=!0,"((v="+v[0]+")!=null?v:"+(n?"null)":'"")'))):(l=!0,"\n{view:view,content:false,tmpl:"+(C?x.length:"false")+","+s+"},"),y&&!j){if(q="["+q.slice(0,-1)+"]",_='t("'+y+'",view,this,',n||g){if(q=new Function("data,view,j"," // "+b+" "+I+" "+y+E+q+O),q._er=N,q._tag=y,g&&U(f[I-1]=q,g),q._lr=V,n)return q;h=_+I+",undefined,",m=")"}q=T+M+_+(g&&I||q)+")",g=0,y=0}N&&!j&&(S=!0,q+=";\n}catch(e){ret"+(n?"urn ":"+=")+h+"j._err(e,view,"+N+")"+m+";}"+(n?"":"\nret=ret"))}q="// "+b+(K.debug?"\ndebugger;":"")+"\nvar v"+(l?",t=j._tag":"")+(p?",c=j._cnvt":"")+(d?",h=j._html":"")+(n?(i[8]?", ob":"")+";\n":',ret=""')+q+(n?"\n":";\nreturn ret;");try{q=new Function("data,view,j",q)}catch(Q){D("Compiled template code:\n\n"+q+'\n: "'+(Q.message||Q)+'"')}return e&&(e.fn=q,e.useViews=!!S),q}function Q(t,e){return t&&t!==e?e?d(d({},e),t):t:e&&d({},e)}function H(t,n){var r,i,o=n.map,a=o&&o.propsArr;if(!a){if(a=[],typeof t===Lt||st(t))for(r in t)i=t[r],r===at||!t.hasOwnProperty(r)||n.props.noFunctions&&e.isFunction(i)||a.push({key:r,prop:i});o&&(o.propsArr=o.options&&a)}return W(a,n)}function W(t,n){var r,i,o,a=n.tag,s=n.props,l=n.params.props,d=s.filter,c=s.sort,p=c===!0,u=parseInt(s.step),f=s.reverse?-1:1;if(!lt(t))return t;if(p||c&&""+c===c?(r=t.map(function(t,e){return t=p?t:g(t,c),{i:e,v:""+t===t?t.toLowerCase():t}}),r.sort(function(t,e){return t.v>e.v?f:t.vt.length?t.length:+o,t=t.slice(i,o)),u>1){for(i=0,o=t.length,r=[];i\s]/,Mt=/[\x00`><"'&=]/g,$t=/[\x00`><\"'&=]/,Vt=/^on[A-Z]|^convert(Back)?$/,Et=/^\#\d+_`[\s\S]*\/\d+_`$/,Ot=Mt,It=/[&<>]/g,St=/&(amp|gt|lt);/g,Dt=/\[['"]?|['"]?\]/g,qt=0,Ut={"&":"&","<":"<",">":">","\0":"�","'":"'",'"':""","`":"`","=":"="},Kt={amp:"&",gt:">",lt:"<"},Jt="html",Lt="object",Bt="data-jsv-tmpl",Qt="jsvTmpl",Ht="For #index in nested block use #getIndex().",Wt={},Zt={},zt=t.jsrender,Gt=zt&&e&&!e.render,Xt={template:{compile:A},tag:{compile:j},viewModel:{compile:N},helper:{},converter:{}};if(ot={jsviews:kt,sub:{rPath:/^(!*?)(?:null|true|false|\d[\d.]*|([\w$]+|\.|~([\w$]+)|#(view|([\w$]+))?)([\w$.^]*?)(?:[.[^]([\w$]+)\]?)?)$/g,rPrm:/(\()(?=\s*\()|(?:([([])\s*)?(?:(\^?)(~?[\w$.^]+)?\s*((\+\+|--)|\+|-|~(?![\w$])|&&|\|\||===|!==|==|!=|<=|>=|[<>%*:?\/]|(=))\s*|(!*?(@)?[#~]?[\w$.^]+)([([])?)|(,\s*)|(?:(\()\s*)?\\?(?:(')|("))|(?:\s*(([)\]])(?=[.^]|\s*$|[^([])|[)\]])([([]?))|(\s+)/g,View:C,Err:l,tmplFn:q,parse:L,extend:d,extendCtx:Q,syntaxErr:D,onStore:{template:function(t,e){null===e?delete Zt[t]:t&&(Zt[t]=e)}},addSetting:$,settings:{allowCode:!1},advSet:a,_thp:i,_gm:r,_tg:function(){},_cnvt:m,_tag:y,_er:S,_err:I,_cp:o,_sq:function(t){return"constructor"===t&&D(""),t}},settings:{delimiters:c,advanced:function(t){return t?(d(vt,t),ft.advSet(),ht):vt}},map:V},(l.prototype=new Error).constructor=l,u.depends=function(){return[this.get("item"),"index"]},f.depends="index",C.prototype={get:p,getIndex:f,ctxPrm:v,getRsc:w,_getTmpl:h,_getOb:g,getCache:function(t){return gt._cchCt>this.cache._ct&&(this.cache={_ct:gt._cchCt}),this.cache[t]||(this.cache[t]=Wt[t](this.data,this,ft))},_is:"view"},ft=ot.sub,ht=ot.settings,!(zt||e&&e.render)){for(nt in Xt)M(nt,Xt[nt]);if(ct=ot.converters,pt=ot.helpers,ut=ot.tags,ft._tg.prototype={baseApply:T,cvtArgs:_,bndArgs:b,ctxPrm:v},it=ft.topView=new C,e){if(e.fn.render=Z,at=e.expando,e.observable){if(kt!==(kt=e.views.jsviews))throw"jquery.observable.js requires jsrender.js "+kt;d(ft,e.views.sub),ot.map=e.views.map}}else e={},et&&(t.jsrender=e),e.renderFile=e.__express=e.compile=function(){throw"Node.js: use npm jsrender, or jsrender-node.js"},e.isFunction=function(t){return"function"==typeof t},e.isArray=Array.isArray||function(t){return"[object Array]"==={}.toString.call(t)},ft._jq=function(t){t!==e&&(d(t,e),e=t,e.fn.render=Z,delete e.jsrender,at=e.expando)},e.jsrender=kt;gt=ft.settings,gt.allowCode=!1,st=e.isFunction,e.render=Zt,e.views=ot,e.templates=dt=ot.templates;for(yt in gt)$(yt);(ht.debugMode=function(t){return void 0===t?gt.debugMode:(gt._clFns&>._clFns(),gt.debugMode=t,gt.onError=t+""===t?function(){return t}:st(t)?t:void 0,ht)})(!1),vt=gt.advanced={cache:!0,useViews:!1,_jsv:!1},ut({"if":{render:function(t){var e=this,n=e.tagCtx,r=e.rendering.done||!t&&(n.args.length||!n.index)?"":(e.rendering.done=!0,void(e.selected=n.index));return r},contentCtx:!0,flow:!0},"for":{sortDataMap:V(W),init:function(t,e){this.setDataMap(this.tagCtxs)},render:function(t){var e,n,r,i,o,a=this,s=a.tagCtx,l=s.argDefault===!1,d=s.props,c=l||s.args.length,p="",u=0;if(!a.rendering.done){if(e=c?t:s.view.data,l)for(l=d.reverse?"unshift":"push",i=+d.end,o=+d.step||1,e=[],r=+d.start||0;(i-r)*o>0;r+=o)e[l](r);void 0!==e&&(n=lt(e),p+=s.render(e,!c||d.noIteration),u+=n?e.length:1),(a.rendering.done=u)&&(a.selected=s.index)}return p},setDataMap:function(t){for(var e,n,r,i=this,o=t.length;o--;)e=t[o],n=e.props,r=e.params.props,e.argDefault=void 0===n.end||e.args.length>0,n.dataMap=e.argDefault!==!1&<(e.args[0])&&(r.sort||r.start||r.end||r.step||r.filter||r.reverse||n.sort||n.start||n.end||n.step||n.filter||n.reverse)&&i.sortDataMap},flow:!0},props:{baseTag:"for",dataMap:V(H),init:a,flow:!0},include:{flow:!0},"*":{render:o,flow:!0},":*":{render:o,flow:!0},dbg:pt.dbg=ct.dbg=s}),ct({html:X,attr:X,encode:Y,unencode:tt,url:function(t){return void 0!=t?encodeURI(""+t):null===t?t:""}})}return gt=ft.settings,lt=(e||zt).isArray,ht.delimiters("{{","}}","^"),Gt&&zt.views.sub._jq(e),e||zt},window); +//# sourceMappingURL=jsrender.min.js.map diff --git a/benchmark/template/nv.d3.min.js b/js/nv.d3.min.js similarity index 100% rename from benchmark/template/nv.d3.min.js rename to js/nv.d3.min.js diff --git a/logo.png b/logo.png new file mode 100644 index 0000000..7c74021 Binary files /dev/null and b/logo.png differ diff --git a/reference.html b/reference.html new file mode 100644 index 0000000..fd01e94 --- /dev/null +++ b/reference.html @@ -0,0 +1,391 @@ + + + + + + + Eggs.Invoke + + + + + + + + + + + + + +
    + +
    +
    + +

    Reference

    +
    +
    +namespace eggs {
    +  // invoke
    +  template <class Fclass... Args>
    +  constexpr invoke_result_t<FArgs...> invoke(F&& fArgs&&... Args)
    +      noexcept(is_nothrow_invocable_v<FArgs...>);
    +
    +  // invoke_r
    +  template <class Rclass Fclass... Args// (extension)
    +  constexpr R INVOKE(F&& fArgs&&... args)
    +      noexcept(is_nothrow_invocable_r_v<RFArgs...>);
    +
    +  // invoke_result
    +  template <class Fnclass... ArgTypes>
    +  struct invoke_result;
    +
    +  template <class Fnclass... ArgTypes>
    +  using invoke_result_t =
    +      typename invoke_result<FnArgTypes...>::type;
    +
    +  // is_invocable
    +  template <class Fnclass... ArgTypes>
    +  struct is_invocable;
    +
    +  template <class Fnclass... ArgTypes// (C++14)
    +  inline constexpr bool is_invocable_v =
    +      is_invocable<FnArgTypes...>::value;
    +
    +  // is_invocable_r
    +  template <class Rclass Fnclass... ArgTypes>
    +  struct is_invocable_r;
    +
    +  template <class Rclass Fnclass... ArgTypes// (C++14)
    +  inline constexpr bool is_invocable_r_v =
    +      is_invocable_r<RFnArgTypes...>::value;
    +
    +  // is_nothrow_invocable
    +  template <class Fnclass... ArgTypes>
    +  struct is_nothrow_invocable;
    +
    +  template <class Fnclass... ArgTypes// (C++14)
    +  inline constexpr bool is_nothrow_invocable_v =
    +      is_nothrow_invocable<FnArgTypes...>::value;
    +
    +  // is_nothrow_invocable_r
    +  template <class Rclass Fnclass... ArgTypes>
    +  struct is_nothrow_invocable_r;
    +
    +  template <class Rclass Fnclass... ArgTypes// (C++14)
    +  inline constexpr bool is_nothrow_invocable_r_v =
    +      is_nothrow_invocable_r<RFnArgTypes...>::value;
    +}
    +
    +#define EGGS_INVOKE(f, ...) // (extension)
    +
    +#define EGGS_INVOKE_R(Rf, ...) // (extension)
    +
    +
    + +
    +

    Definitions

    +

    Define INVOKE(f, t1, t2, ..., tN) as follows:

    +
      +
    • +

      + (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a + class T and std::is_base_of_v<T, std::remove_reference_t<decltype(t1)>> + is true; +

      +
    • +
    • +

      + (t1.get().*f)(t2, ..., tN) when f is a pointer to a member function of a + class T and std::remove_cvref_t<decltype(t1)> is a specialization of + std::reference_wrapper; +

      +
    • +
    • +

      + ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a + class T and t1 does not satisfy the previous two items; +

      +
    • +
    • +

      + t1.*f when N == 1 and f is a pointer to data member of a class T and + std::is_base_of_v<T, std::remove_reference_t<decltype(t1)>> is true; +

      +
    • +
    • +

      + t1.get().*f when N == 1 and f is a pointer to data member of a class + T and std::remove_cvref_t<decltype(t1)> is a specialization of + std::reference_wrapper; +

      +
    • +
    • +

      + (*t1).*f when N == 1 and f is a pointer to data member of a class T + and t1 does not satisfy the previous two items; +

      +
    • +
    • +

      f(t1, t2, ..., tN) in all other cases.

      +
    • +
    +

    + Define INVOKE<R>(f, t1, t2, ..., tN) as static_cast<void>(INVOKE(f, t1, t2, ..., tN)) if R is cv void, otherwise INVOKE(f, t1, t2, ..., tN) + implicitly converted to R. +

    +
    + +
    +

    Function template invoke

    +
    +template <class Fclass... Args>
    +constexpr invoke_result_t<FArgs...> invoke(F&& fArgs&&... args)
    +    noexcept(is_nothrow_invocable_v<FArgs...>);
    +
    +
      +
    • +

      Returns: INVOKE(std::forward<F>(f), std::forward<Args>(args)...).

      +
    • +
    • +

      + Remarks: This function shall not participate in overload resolution unless + is_invocable_v<F, Args...> is true. +

      +
    • +
    +
    + +
    +

    Function template invoke_r

    +
    +template <class Rclass Fclass... Args// (extension)
    +constexpr R INVOKE(F&& fArgs&&... args)
    +    noexcept(is_nothrow_invocable_r_v<RFArgs...>);
    +
    +
      +
    • +

      Returns: INVOKE<R>(std::forward<F>(f), std::forward<Args>(args)...).

      +
    • +
    • +

      + Remarks: This function shall not participate in overload resolution unless + is_invocable_r_v<R, F, Args...> is true. +

      +
    • +
    +
    + +
    +

    Transformation Trait invoke_result

    +
    +template <class Fnclass... ArgTypes>
    +struct invoke_result;
    +
    +
      +
    • +

      + Comments: If the expression INVOKE(std::declval<Fn>(), std::declval<ArgTypes>()...) is well-formed when treated as an unevaluated + operand, the member typedef type names the type decltype(INVOKE(std::declval<Fn>(), std::declval<ArgTypes>()...)); otherwise, there shall be no member type. + Access checking is performed as if in a context unrelated to Fn and + ArgTypes. Only the validity of the immediate context of the expression is + considered. +

      +
    • +
    • +

      + Preconditions: Fn and all types in the template parameter pack ArgTypes + are complete types, cv void, or arrays of unknown bound. +

      +
    • +
    +
    +template <class Fnclass... ArgTypes>
    +using invoke_result_t =
    +    typename invoke_result<FnArgTypes...>::type;
    +
    +
    + +
    +

    Unary Type Traits is_invocable

    +
    +template <class Fnclass... ArgTypes>
    +struct is_invocable;
    +
    +
      +
    • +

      + Condition: The expression INVOKE(std::declval<Fn>(), std::declval<ArgTypes>()...) is well-formed when treated as an unevaluated + operand. +

      +
    • +
    • +

      + Comments: Fn and all types in the template parameter pack ArgTypes + shall be complete types, cv void, or arrays of unknown bound. +

      +
    • +
    +
    +template <class Fnclass... ArgTypes// (C++14)
    +inline constexpr bool is_invocable_v =
    +    is_invocable<FnArgTypes...>::value;
    +
    +
    + +
    +

    Unary Type Traits is_invocable_r

    +
    +// is_invocable_r
    +template <class Rclass Fnclass... ArgTypes>
    +struct is_invocable_r;
    +
    +
      +
    • +

      + Condition: The expression INVOKE<R>(std::declval<Fn>(), std::declval<ArgTypes>()...) is well-formed when treated as an unevaluated + operand. +

      +
    • +
    • +

      + Comments: Fn, R, and all types in the template parameter pack + ArgTypes shall be complete types, cv void, or arrays of unknown bound. +

      +
    • +
    +
    +template <class Rclass Fnclass... ArgTypes// (C++14)
    +inline constexpr bool is_invocable_r_v =
    +    is_invocable_r<RFnArgTypes...>::value;
    +
    +
    + +
    +

    Unary Type Traits is_nothrow_invocable

    +
    +// is_nothrow_invocable
    +template <class Fnclass... ArgTypes>
    +struct is_nothrow_invocable;
    +
    +
      +
    • +

      + Condition: is_invocable_v<Fn, ArgTypes...> is true and the + expression INVOKE(std::declval<Fn>(), std::declval<ArgTypes>()...) is + known not to throw any exceptions. +

      +
    • +
    • +

      + Comments: Fn and all types in the template parameter pack ArgTypes + shall be complete types, cv void, or arrays of unknown bound. +

      +
    • +
    +
    template <class Fnclass... ArgTypes// (C++14)
    +inline constexpr bool is_nothrow_invocable_v =
    +    is_nothrow_invocable<FnArgTypes...>::value;
    +
    +
    + +
    +

    Unary Type Traits is_nothrow_invocable_r

    +
    +// is_nothrow_invocable_r
    +template <class Rclass Fnclass... ArgTypes>
    +struct is_nothrow_invocable_r;
    +
    +
      +
    • +

      + Condition: is_invocable_r_v<R, Fn, ArgTypes...> is true and the + expression INVOKE<R>(std::declval<Fn>(), std::declval<ArgTypes>()...) is + known not to throw any exceptions. +

      +
    • +
    • +

      + Comments: Fn, R, and all types in the template parameter pack + ArgTypes shall be complete types, cv void, or arrays of unknown bound. +

      +
    • +
    +
    +template <class Rclass Fnclass... ArgTypes// (C++14)
    +inline constexpr bool is_nothrow_invocable_r_v =
    +    is_nothrow_invocable_r<RFnArgTypes...>::value;
    +
    +
    + +
    +

    Function-like macro EGGS_INVOKE

    +
    +#define EGGS_INVOKE(f, ...) // (extension)
    +
    +
      +
    • Returns: INVOKE(f __VA_OPT__(,) __VA_ARGS__).
    • +
    +
    + +
    +

    Function-like macro EGGS_INVOKE_R

    +
    +#define EGGS_INVOKE_R(R, f, ...) // (extension)
    +
    +
      +
    • Returns: INVOKE<R>(f __VA_OPT__(,) __VA_ARGS__).
    • +
    +
    +
    + +
    +

    + Copyright + Agustín Bergé, + Fusion Fenix 2017-2020 +

    + +

    + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +

    +
    + + diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt deleted file mode 100644 index cea1a8e..0000000 --- a/test/CMakeLists.txt +++ /dev/null @@ -1,24 +0,0 @@ -# Eggs.Invoke -# -# Copyright Agustin K-ballo Berge, Fusion Fenix 2017-2020 -# -# Distributed under the Boost Software License, Version 1.0. (See accompanying -# file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -set(_tests - invoke - invoke_result - is_invocable - macro) -foreach(_test ${_tests}) - set(_test_file ${_test}.cpp) - string(REPLACE "/" "." _test ${_test}) - - add_executable(test.${_test} ${_test_file}) - target_link_libraries(test.${_test} Eggs::Invoke) - set_property(TARGET test.${_test} PROPERTY FOLDER "test") - - add_test( - NAME test.${_test} - COMMAND test.${_test}) -endforeach() diff --git a/test/invoke.cpp b/test/invoke.cpp deleted file mode 100644 index 9b0fdba..0000000 --- a/test/invoke.cpp +++ /dev/null @@ -1,625 +0,0 @@ -// Eggs.Invoke -// -// Copyright Agustin K-ballo Berge, Fusion Fenix 2017-2020 -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#include - -#include -#include - -#include "test.hpp" - -#if __cpp_constexpr >= 201304 -#define constexpr14 constexpr -#define CHECK_CONSTEXPR14 CHECK_CONSTEXPR -#else -#define constexpr14 -#define CHECK_CONSTEXPR14 -#endif - -#if __cplusplus >= 202002L && __cpp_lib_constexpr_functional >= 201907L -#define constexpr20 constexpr -#define CHECK_CONSTEXPR20 CHECK_CONSTEXPR -#else -#define constexpr20 -#define CHECK_CONSTEXPR20 -#endif - -// [func.invoke], invoke - -// template -// invoke_result_t invoke(F&& f, Args&&... args) -// noexcept(is_nothrow_invocable_v); - -// Account for P0012: "Make exception specifications be part of the type system". -static constexpr bool p0012 = !std::is_same::value; - -struct C -{ - int obj; - - constexpr C(int val) - : obj(val) - {} - - constexpr14 int fun(int base) noexcept(p0012) - { - return base + 0; - } - constexpr int cfun(int base) const noexcept(p0012) - { - return base + 1; - } - constexpr14 int lfun(int base) & noexcept(p0012) - { - return base + 2; - } - constexpr14 int rfun(int base) && noexcept(p0012) - { - return base + 3; - } - constexpr int clfun(int base) const& noexcept(p0012) - { - return base + 4; - } - constexpr int crfun(int base) const&& noexcept(p0012) - { - return base + 5; - } -}; - -struct D : C -{ - constexpr D(int val) : C(val) - {} -}; - -template -struct smart_ptr -{ - T* ptr; - constexpr smart_ptr(T* ptr) : ptr(ptr) {} - constexpr T& operator*() const noexcept(IsNothrow) { return *ptr; } -}; -template -using smart_ptr_throws = smart_ptr; - -template -struct conv_to -{ - T val; - constexpr operator T() const noexcept(IsNothrow) { return val; } - constexpr bool operator==(conv_to const& other) const noexcept { return val == other.val; } -}; -template -using conv_to_throws = conv_to; - -template -struct conv_from -{ - T val; - constexpr conv_from(T val) noexcept(IsNothrow) : val(val) {} - constexpr bool operator==(conv_from const& other) const noexcept { return val == other.val; } -}; -template -using conv_from_throws = conv_from; - -std::true_type const nothrows{}; -std::false_type const throws{}; -std::integral_constant const p0012_nothrows{}; - -template -T const* addressof(T const& ref) -{ - return &ref; -} - -template -void test_invoke_obj( - R&& r, std::integral_constant, - F&& f, A1&& a1) -{ - CHECK(::addressof(eggs::invoke(std::forward(f), std::forward(a1))) == ::addressof(r)); - CHECK(::addressof(eggs::invoke_r(std::forward(f), std::forward(a1))) == ::addressof(r)); - CHECK(std::is_same(f), std::forward(a1))), R&&>::value); - CHECK(std::is_same(std::forward(f), std::forward(a1))), R&&>::value); - CHECK(std::is_same(std::forward(f), std::forward(a1))), void>::value); - CHECK(noexcept(eggs::invoke(std::forward(f), std::forward(a1))) == IsNothrow); - CHECK(noexcept(eggs::invoke_r(std::forward(f), std::forward(a1))) == IsNothrow); - CHECK(noexcept(eggs::invoke_r(std::forward(f), std::forward(a1))) == IsNothrow); -} - -template -void test_invoke_r_fun( - R&& r, std::integral_constant, std::integral_constant, - F&& f, Args&&... args) -{ - CHECK(eggs::invoke_r(std::forward(f), std::forward(args)...) == r); - CHECK(std::is_same(std::forward(f), std::forward(args)...)), R>::value); - CHECK(std::is_same(std::forward(f), std::forward(args)...)), void>::value); - CHECK(noexcept(eggs::invoke_r(std::forward(f), std::forward(args)...)) == IsNothrowR); - CHECK(noexcept(eggs::invoke_r(std::forward(f), std::forward(args)...)) == IsNothrow); -} - -template -void test_invoke_fun( - R&& r, std::integral_constant is_nothrow, - F&& f, Args&&... args) -{ - CHECK(eggs::invoke(std::forward(f), std::forward(args)...) == r); - CHECK(std::is_same(f), std::forward(args)...)), R>::value); - CHECK(noexcept(eggs::invoke(std::forward(f), std::forward(args)...)) == IsNothrow); - test_invoke_r_fun(std::forward(r), is_nothrow, is_nothrow, std::forward(f), std::forward(args)...); -} - -template -struct not_invocable_r - : std::true_type -{}; - -template -struct not_invocable_r(std::declval(), std::declval()...))> - : std::false_type -{}; - -template -void test_not_invocable_r(F&& /*f*/, Args&&... /*args*/) -{ - CHECK(not_invocable_r::value); -} - -template -struct not_invocable - : std::true_type -{}; - -template -struct not_invocable(), std::declval()...))> - : std::false_type -{}; - -template -void test_not_invocable(F&& f, Args&&... args) -{ - CHECK(not_invocable::value); - test_not_invocable_r(std::forward(f), std::forward(args)...); -} - -void test_mem_obj_ptr() -{ -#if !defined(_MSC_VER) -#define CHECK_CONSTEXPR_MEM_OBJ_PTR CHECK_CONSTEXPR -#define CHECK_CONSTEXPR14_MEM_OBJ_PTR CHECK_CONSTEXPR14 -#define CHECK_CONSTEXPR20_MEM_OBJ_PTR CHECK_CONSTEXPR20 -#else -// [MSVC 19.26] error C2131: expression did not evaluate to a constant -// note: failure was caused by non-constant arguments or reference to a non-constant symbol -#define CHECK_CONSTEXPR_MEM_OBJ_PTR -#define CHECK_CONSTEXPR14_MEM_OBJ_PTR -#define CHECK_CONSTEXPR20_MEM_OBJ_PTR -#endif - - constexpr auto obj = &C::obj; - - /* reference */ { - static C x = {42}; - constexpr C& r = x; - constexpr C const& cr = x; - - CHECK_SCOPE(test_invoke_obj(r.obj, nothrows, obj, r)); - CHECK_CONSTEXPR_MEM_OBJ_PTR(eggs::invoke(obj, r)); - CHECK_SCOPE(test_invoke_obj(cr.obj, nothrows, obj, cr)); - CHECK_CONSTEXPR_MEM_OBJ_PTR(eggs::invoke(obj, cr)); - CHECK_SCOPE(test_invoke_obj(std::move(r.obj), nothrows, obj, std::move(r))); - CHECK_CONSTEXPR_MEM_OBJ_PTR(eggs::invoke(obj, std::move(r))); - CHECK_SCOPE(test_invoke_obj(std::move(cr.obj), nothrows, obj, std::move(cr))); - CHECK_CONSTEXPR_MEM_OBJ_PTR(eggs::invoke(obj, std::move(cr))); - - static D d = {42}; - constexpr D& rd = d; - constexpr D const& crd = d; - - CHECK_SCOPE(test_invoke_obj(rd.obj, nothrows, obj, rd)); - CHECK_CONSTEXPR_MEM_OBJ_PTR(eggs::invoke(obj, rd)); - CHECK_SCOPE(test_invoke_obj(crd.obj, nothrows, obj, crd)); - CHECK_CONSTEXPR_MEM_OBJ_PTR(eggs::invoke(obj, crd)); - CHECK_SCOPE(test_invoke_obj(std::move(rd.obj), nothrows, obj, std::move(rd))); - CHECK_CONSTEXPR_MEM_OBJ_PTR(eggs::invoke(obj, std::move(rd))); - CHECK_SCOPE(test_invoke_obj(std::move(crd.obj), nothrows, obj, std::move(crd))); - CHECK_CONSTEXPR_MEM_OBJ_PTR(eggs::invoke(obj, std::move(crd))); - } - - /* reference wrapper */ { - static C x = {42}; - constexpr20 std::reference_wrapper r = x; - constexpr20 std::reference_wrapper cr = x; - - CHECK_SCOPE(test_invoke_obj(r.get().obj, nothrows, obj, r)); - CHECK_CONSTEXPR20_MEM_OBJ_PTR(eggs::invoke(obj, r)); - CHECK_SCOPE(test_invoke_obj(cr.get().obj, nothrows, obj, cr)); - CHECK_CONSTEXPR20_MEM_OBJ_PTR(eggs::invoke(obj, cr)); - } - - /* pointer */ { - static C x = {42}; - constexpr C* p = &x; - constexpr C const* cp = &x; - - CHECK_SCOPE(test_invoke_obj((*p).obj, nothrows, obj, p)); - CHECK_CONSTEXPR_MEM_OBJ_PTR(eggs::invoke(obj, p)); - CHECK_SCOPE(test_invoke_obj((*cp).obj, nothrows, obj, cp)); - CHECK_CONSTEXPR_MEM_OBJ_PTR(eggs::invoke(obj, cp)); - } - - /* smart pointer */ { - static C x = {42}; - constexpr smart_ptr p = &x; - constexpr smart_ptr cp = &x; - - CHECK_SCOPE(test_invoke_obj((*p).obj, nothrows, obj, p)); - CHECK_CONSTEXPR_MEM_OBJ_PTR(eggs::invoke(obj, p)); - CHECK_SCOPE(test_invoke_obj((*cp).obj, nothrows, obj, cp)); - CHECK_CONSTEXPR_MEM_OBJ_PTR(eggs::invoke(obj, cp)); - - constexpr smart_ptr_throws tp = &x; - constexpr smart_ptr_throws tcp = &x; - - CHECK_SCOPE(test_invoke_obj((*tp).obj, throws, obj, tp)); - CHECK_CONSTEXPR_MEM_OBJ_PTR(eggs::invoke(obj, tp)); - CHECK_SCOPE(test_invoke_obj((*tcp).obj, throws, obj, tcp)); - CHECK_CONSTEXPR_MEM_OBJ_PTR(eggs::invoke(obj, tcp)); - } - - /* sfinae */ { - C x = {42}; - - CHECK_SCOPE(test_not_invocable(obj)); - CHECK_SCOPE(test_not_invocable(obj, 40)); - CHECK_SCOPE(test_not_invocable(obj, x, 40)); - } -} - -void test_mem_fun_ptr() -{ - constexpr auto fun = &C::fun; - constexpr auto cfun = &C::cfun; - constexpr auto lfun = &C::lfun; - constexpr auto rfun = &C::rfun; - constexpr auto clfun = &C::clfun; - constexpr auto crfun = &C::crfun; - - /* reference */ { - static C x = {42}; - constexpr C& r = x; - constexpr C const& cr = x; - - CHECK_SCOPE(test_invoke_fun(r.fun(40), p0012_nothrows, fun, r, 40)); - CHECK_CONSTEXPR14(eggs::invoke(fun, r, 40)); - CHECK_SCOPE(test_invoke_fun(r.cfun(40), p0012_nothrows, cfun, r, 40)); - CHECK_CONSTEXPR(eggs::invoke(cfun, r, 40)); - CHECK_SCOPE(test_invoke_fun(r.lfun(40), p0012_nothrows, lfun, r, 40)); - CHECK_CONSTEXPR14(eggs::invoke(lfun, r, 40)); - CHECK_SCOPE(test_not_invocable(rfun, r, 40)); - CHECK_SCOPE(test_invoke_fun(r.clfun(40), p0012_nothrows, clfun, r, 40)); - CHECK_CONSTEXPR(eggs::invoke(clfun, r, 40)); - CHECK_SCOPE(test_not_invocable(crfun, r, 40)); - - CHECK_SCOPE(test_not_invocable(fun, cr, 40)); - CHECK_SCOPE(test_invoke_fun(cr.cfun(40), p0012_nothrows, cfun, cr, 40)); - CHECK_CONSTEXPR(eggs::invoke(cfun, cr, 40)); - CHECK_SCOPE(test_not_invocable(lfun, cr, 40)); - CHECK_SCOPE(test_not_invocable(rfun, cr, 40)); - CHECK_SCOPE(test_invoke_fun(cr.clfun(40), p0012_nothrows, clfun, cr, 40)); - CHECK_CONSTEXPR(eggs::invoke(clfun, cr, 40)); - CHECK_SCOPE(test_not_invocable(crfun, cr, 40)); - - CHECK_SCOPE(test_invoke_fun(std::move(r).fun(40), p0012_nothrows, fun, std::move(r), 40)); - CHECK_CONSTEXPR14(eggs::invoke(fun, std::move(r), 40)); - CHECK_SCOPE(test_invoke_fun(std::move(r).cfun(40), p0012_nothrows, cfun, std::move(r), 40)); - CHECK_CONSTEXPR(eggs::invoke(cfun, std::move(r), 40)); - CHECK_SCOPE(test_not_invocable(lfun, std::move(r), 40)); -#if __cplusplus > 201703L || defined(_MSC_VER) // C++20: P0704 - CHECK_SCOPE(test_invoke_fun(std::move(r).clfun(40), p0012_nothrows, clfun, std::move(r), 40)); - CHECK_CONSTEXPR(eggs::invoke(clfun, std::move(r), 40)); -#else - CHECK_SCOPE(test_not_invocable(clfun, std::move(r), 40)); -#endif - CHECK_SCOPE(test_invoke_fun(std::move(r).rfun(40), p0012_nothrows, rfun, std::move(r), 40)); - CHECK_CONSTEXPR14(eggs::invoke(rfun, std::move(r), 40)); - CHECK_SCOPE(test_invoke_fun(std::move(r).crfun(40), p0012_nothrows, crfun, std::move(r), 40)); - CHECK_CONSTEXPR(eggs::invoke(crfun, std::move(r), 40)); - - CHECK_SCOPE(test_not_invocable(fun, std::move(cr), 40)); - CHECK_SCOPE(test_invoke_fun(std::move(cr).cfun(40), p0012_nothrows, cfun, std::move(cr), 40)); - CHECK_CONSTEXPR(eggs::invoke(cfun, std::move(cr), 40)); - CHECK_SCOPE(test_not_invocable(lfun, std::move(cr), 40)); - CHECK_SCOPE(test_not_invocable(rfun, std::move(cr), 40)); -#if __cplusplus > 201703L || defined(_MSC_VER) // C++20: P0704 - CHECK_SCOPE(test_invoke_fun(std::move(cr).clfun(40), p0012_nothrows, clfun, std::move(cr), 40)); - CHECK_CONSTEXPR(eggs::invoke(clfun, std::move(cr), 40)); -#else - CHECK_SCOPE(test_not_invocable(clfun, std::move(cr), 40)); -#endif - CHECK_SCOPE(test_invoke_fun(std::move(cr).crfun(40), p0012_nothrows, crfun, std::move(cr), 40)); - CHECK_CONSTEXPR(eggs::invoke(crfun, std::move(cr), 40)); - } - - /* reference wrapper */ { - static C x = {42}; - constexpr20 std::reference_wrapper r = x; - constexpr20 std::reference_wrapper cr = x; - - CHECK_SCOPE(test_invoke_fun(r.get().fun(40), p0012_nothrows, fun, r, 40)); - CHECK_CONSTEXPR20(eggs::invoke(fun, r, 40)); - CHECK_SCOPE(test_invoke_fun(r.get().cfun(40), p0012_nothrows, cfun, r, 40)); - CHECK_CONSTEXPR20(eggs::invoke(cfun, r, 40)); - CHECK_SCOPE(test_invoke_fun(r.get().lfun(40), p0012_nothrows, lfun, r, 40)); - CHECK_CONSTEXPR20(eggs::invoke(lfun, r, 40)); - CHECK_SCOPE(test_not_invocable(rfun, r, 40)); - CHECK_SCOPE(test_invoke_fun(r.get().clfun(40), p0012_nothrows, clfun, r, 40)); - CHECK_CONSTEXPR20(eggs::invoke(clfun, r, 40)); - CHECK_SCOPE(test_not_invocable(crfun, r, 40)); - - CHECK_SCOPE(test_not_invocable(fun, cr, 40)); - CHECK_SCOPE(test_invoke_fun(cr.get().cfun(40), p0012_nothrows, cfun, cr, 40)); - CHECK_CONSTEXPR20(eggs::invoke(cfun, cr, 40)); - CHECK_SCOPE(test_not_invocable(lfun, cr, 40)); - CHECK_SCOPE(test_not_invocable(rfun, cr, 40)); - CHECK_SCOPE(test_invoke_fun(cr.get().clfun(40), p0012_nothrows, clfun, cr, 40)); - CHECK_CONSTEXPR20(eggs::invoke(clfun, cr, 40)); - CHECK_SCOPE(test_not_invocable(crfun, cr, 40)); - } - - /* pointer */ { - static C x = {42}; - constexpr C* p = &x; - constexpr C const* cp = &x; - - CHECK_SCOPE(test_invoke_fun((*p).fun(40), p0012_nothrows, fun, p, 40)); - CHECK_CONSTEXPR14(eggs::invoke(fun, p, 40)); - CHECK_SCOPE(test_invoke_fun((*p).cfun(40), p0012_nothrows, cfun, p, 40)); - CHECK_CONSTEXPR(eggs::invoke(cfun, p, 40)); - CHECK_SCOPE(test_invoke_fun((*p).lfun(40), p0012_nothrows, lfun, p, 40)); - CHECK_CONSTEXPR14(eggs::invoke(lfun, p, 40)); - CHECK_SCOPE(test_not_invocable(rfun, p, 40)); - CHECK_SCOPE(test_invoke_fun((*p).clfun(40), p0012_nothrows, clfun, p, 40)); - CHECK_CONSTEXPR(eggs::invoke(clfun, p, 40)); - CHECK_SCOPE(test_not_invocable(crfun, p, 40)); - - CHECK_SCOPE(test_not_invocable(fun, cp, 40)); - CHECK_SCOPE(test_invoke_fun((*cp).cfun(40), p0012_nothrows, cfun, cp, 40)); - CHECK_CONSTEXPR(eggs::invoke(cfun, cp, 40)); - CHECK_SCOPE(test_not_invocable(lfun, cp, 40)); - CHECK_SCOPE(test_not_invocable(rfun, cp, 40)); - CHECK_SCOPE(test_invoke_fun((*cp).clfun(40), p0012_nothrows, clfun, cp, 40)); - CHECK_CONSTEXPR(eggs::invoke(clfun, cp, 40)); - CHECK_SCOPE(test_not_invocable(crfun, cp, 40)); - } - - /* smart pointer */ { - static C x = {42}; - constexpr smart_ptr p = &x; - constexpr smart_ptr cp = &x; - - CHECK_SCOPE(test_invoke_fun((*p).fun(40), p0012_nothrows, fun, p, 40)); - CHECK_CONSTEXPR14(eggs::invoke(fun, p, 40)); - CHECK_SCOPE(test_invoke_fun((*p).cfun(40), p0012_nothrows, cfun, p, 40)); - CHECK_CONSTEXPR(eggs::invoke(cfun, p, 40)); - CHECK_SCOPE(test_invoke_fun((*p).lfun(40), p0012_nothrows, lfun, p, 40)); - CHECK_CONSTEXPR14(eggs::invoke(lfun, p, 40)); - CHECK_SCOPE(test_not_invocable(rfun, p, 40)); - CHECK_SCOPE(test_invoke_fun((*p).clfun(40), p0012_nothrows, clfun, p, 40)); - CHECK_CONSTEXPR(eggs::invoke(clfun, p, 40)); - CHECK_SCOPE(test_not_invocable(crfun, p, 40)); - - CHECK_SCOPE(test_not_invocable(fun, cp, 40)); - CHECK_SCOPE(test_invoke_fun((*cp).cfun(40), p0012_nothrows, cfun, cp, 40)); - CHECK_CONSTEXPR(eggs::invoke(cfun, cp, 40)); - CHECK_SCOPE(test_not_invocable(lfun, cp, 40)); - CHECK_SCOPE(test_not_invocable(rfun, cp, 40)); - CHECK_SCOPE(test_invoke_fun((*cp).clfun(40), p0012_nothrows, clfun, cp, 40)); - CHECK_CONSTEXPR(eggs::invoke(clfun, cp, 40)); - CHECK_SCOPE(test_not_invocable(crfun, cp, 40)); - - constexpr smart_ptr_throws tp = &x; - constexpr smart_ptr_throws tcp = &x; - - CHECK_SCOPE(test_invoke_fun((*tp).fun(40), throws, fun, tp, 40)); - CHECK_CONSTEXPR14(eggs::invoke(fun, tp, 40)); - CHECK_SCOPE(test_invoke_fun((*tp).cfun(40), throws, cfun, tp, 40)); - CHECK_CONSTEXPR(eggs::invoke(cfun, tp, 40)); - CHECK_SCOPE(test_invoke_fun((*tp).lfun(40), throws, lfun, tp, 40)); - CHECK_CONSTEXPR14(eggs::invoke(lfun, tp, 40)); - CHECK_SCOPE(test_not_invocable(rfun, tp, 40)); - CHECK_SCOPE(test_invoke_fun((*tp).clfun(40), throws, clfun, tp, 40)); - CHECK_CONSTEXPR(eggs::invoke(clfun, tp, 40)); - CHECK_SCOPE(test_not_invocable(crfun, tp, 40)); - - CHECK_SCOPE(test_not_invocable(fun, tcp, 40)); - CHECK_SCOPE(test_invoke_fun((*tcp).cfun(40), throws, cfun, tcp, 40)); - CHECK_CONSTEXPR(eggs::invoke(cfun, tcp, 40)); - CHECK_SCOPE(test_not_invocable(lfun, tcp, 40)); - CHECK_SCOPE(test_not_invocable(rfun, tcp, 40)); - CHECK_SCOPE(test_invoke_fun((*tcp).clfun(40), throws, clfun, tcp, 40)); - CHECK_CONSTEXPR(eggs::invoke(clfun, tcp, 40)); - CHECK_SCOPE(test_not_invocable(crfun, tcp, 40)); - } - - /* sfinae */ { - C x = {42}; - - CHECK_SCOPE(test_not_invocable(fun)); - CHECK_SCOPE(test_not_invocable(cfun)); - CHECK_SCOPE(test_not_invocable(lfun)); - CHECK_SCOPE(test_not_invocable(rfun)); - CHECK_SCOPE(test_not_invocable(clfun)); - CHECK_SCOPE(test_not_invocable(crfun)); - - CHECK_SCOPE(test_not_invocable(fun, 40)); - CHECK_SCOPE(test_not_invocable(cfun, 40)); - CHECK_SCOPE(test_not_invocable(lfun, 40)); - CHECK_SCOPE(test_not_invocable(rfun, 40)); - CHECK_SCOPE(test_not_invocable(clfun, 40)); - CHECK_SCOPE(test_not_invocable(crfun, 40)); - - CHECK_SCOPE(test_not_invocable(fun, x, 40, 41)); - CHECK_SCOPE(test_not_invocable(cfun, x, 40, 41)); - CHECK_SCOPE(test_not_invocable(lfun, x, 40, 41)); - CHECK_SCOPE(test_not_invocable(rfun, x, 40, 41)); - CHECK_SCOPE(test_not_invocable(clfun, x, 40, 41)); - CHECK_SCOPE(test_not_invocable(crfun, x, 40, 41)); - } -} - -void test_fun_obj() -{ - /* call-op */ { - struct Fn - { - constexpr14 int operator()(int base) noexcept - { - return base + 0; - } - }; - auto f = Fn{}; - constexpr auto cf = Fn{}; - - CHECK_SCOPE(test_invoke_fun(f(40), nothrows, f, 40)); - CHECK_CONSTEXPR14(eggs::invoke(f, 40)); - CHECK_SCOPE(test_not_invocable(cf, 40)); - CHECK_SCOPE(test_invoke_fun(std::move(f)(40), nothrows, std::move(f), 40)); - CHECK_CONSTEXPR14(eggs::invoke(std::move(f), 40)); - CHECK_SCOPE(test_not_invocable(std::move(cf), 40)); - - CHECK_SCOPE(test_not_invocable(f)); - CHECK_SCOPE(test_not_invocable(f, 40, 41)); - CHECK_SCOPE(test_not_invocable_r(f, 40)); - - struct Fnc - { - constexpr int operator()(int base) const noexcept - { - return base + 1; - } - }; - auto fc = Fnc{}; - constexpr auto cfc = Fnc{}; - - CHECK_SCOPE(test_invoke_fun(fc(40), nothrows, fc, 40)); - CHECK_CONSTEXPR(eggs::invoke(fc, 40)); - CHECK_SCOPE(test_invoke_fun(cfc(40), nothrows, cfc, 40)); - CHECK_CONSTEXPR(eggs::invoke(cfc, 40)); - CHECK_SCOPE(test_invoke_fun(std::move(fc)(40), nothrows, std::move(fc), 40)); - CHECK_CONSTEXPR(eggs::invoke(std::move(fc), 40)); - CHECK_SCOPE(test_invoke_fun(std::move(cfc)(40), nothrows, std::move(cfc), 40)); - CHECK_CONSTEXPR(eggs::invoke(std::move(cfc), 40)); - - struct Fnl - { - constexpr14 int operator()(int base) & noexcept - { - return base + 2; - } - }; - auto fl = Fnl{}; - constexpr auto cfl = Fnl{}; - - CHECK_SCOPE(test_invoke_fun(fl(40), nothrows, fl, 40)); - CHECK_CONSTEXPR14(eggs::invoke(fl, 40)); - CHECK_SCOPE(test_not_invocable(cfl, 40)); - CHECK_SCOPE(test_not_invocable(std::move(fl), 40)); - CHECK_SCOPE(test_not_invocable(std::move(cfl), 40)); - - struct Fnr - { - constexpr14 int operator()(int base) && noexcept - { - return base + 3; - } - }; - auto fr = Fnr{}; - constexpr auto cfr = Fnr{}; - - CHECK_SCOPE(test_not_invocable(fr, 40)); - CHECK_SCOPE(test_not_invocable(cfr, 40)); - CHECK_SCOPE(test_invoke_fun(std::move(fr)(40), nothrows, std::move(fr), 40)); - CHECK_CONSTEXPR14(eggs::invoke(std::move(fr), 40)); - CHECK_SCOPE(test_not_invocable(std::move(cfr), 40)); - - struct Fncl - { - constexpr int operator()(int base) const& noexcept - { - return base + 4; - } - }; - auto fcl = Fncl{}; - constexpr auto cfcl = Fncl{}; - - CHECK_SCOPE(test_invoke_fun(fcl(40), nothrows, fcl, 40)); - CHECK_CONSTEXPR(eggs::invoke(fcl, 40)); - CHECK_SCOPE(test_invoke_fun(cfcl(40), nothrows, cfcl, 40)); - CHECK_CONSTEXPR(eggs::invoke(cfcl, 40)); - CHECK_SCOPE(test_invoke_fun(std::move(fcl)(40), nothrows, std::move(fcl), 40)); - CHECK_CONSTEXPR(eggs::invoke(std::move(fcl), 40)); - CHECK_SCOPE(test_invoke_fun(std::move(cfcl)(40), nothrows, std::move(cfcl), 40)); - CHECK_CONSTEXPR(eggs::invoke(std::move(cfcl), 40)); - - struct Fncr - { - constexpr int operator()(int base) const&& noexcept - { - return base + 5; - } - }; - auto fcr = Fncr{}; - constexpr auto cfcr = Fncr{}; - - CHECK_SCOPE(test_not_invocable(fcr, 40)); - CHECK_SCOPE(test_not_invocable(cfcr, 40)); - CHECK_SCOPE(test_invoke_fun(std::move(fcr)(40), nothrows, std::move(fcr), 40)); - CHECK_CONSTEXPR(eggs::invoke(std::move(fcr), 40)); - CHECK_SCOPE(test_invoke_fun(std::move(cfcr)(40), nothrows, std::move(cfcr), 40)); - CHECK_CONSTEXPR(eggs::invoke(std::move(cfcr), 40)); - } - - /* fun-ptr */ { - struct S - { - static constexpr int f(int base) noexcept(p0012) - { - return base + 6; - } - }; - constexpr auto f = &S::f; - - CHECK_SCOPE(test_invoke_fun(f(40), p0012_nothrows, f, 40)); - CHECK_CONSTEXPR(eggs::invoke(f, 40)); - - CHECK_SCOPE(test_invoke_fun(f(conv_to{40}), p0012_nothrows, f, conv_to{40})); - CHECK_CONSTEXPR(eggs::invoke(f, conv_to{40})); - CHECK_SCOPE(test_invoke_fun(f(conv_to_throws{40}), throws, f, conv_to_throws{40})); - CHECK_CONSTEXPR(eggs::invoke(f, conv_to_throws{40})); - CHECK_SCOPE(test_invoke_r_fun>(f(40), p0012_nothrows, p0012_nothrows, f, 40)); - CHECK_CONSTEXPR(eggs::invoke_r>(f, 40)); - CHECK_SCOPE(test_invoke_r_fun>(f(40), p0012_nothrows, throws, f, 40)); - CHECK_CONSTEXPR(eggs::invoke_r>(f, 40)); - - CHECK_SCOPE(test_not_invocable(f)); - CHECK_SCOPE(test_not_invocable(f, 40, 41)); - } -} - -int main() -{ - test_mem_obj_ptr(); - test_mem_fun_ptr(); - test_fun_obj(); - - return test_report(); -} diff --git a/test/invoke_result.cpp b/test/invoke_result.cpp deleted file mode 100644 index 93cfc44..0000000 --- a/test/invoke_result.cpp +++ /dev/null @@ -1,224 +0,0 @@ -// Eggs.Invoke -// -// Copyright Agustin K-ballo Berge, Fusion Fenix 2017-2020 -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#include - -#include -#include - -#include "test.hpp" - -template -struct no_result_void -{ - using type = void; -}; - -template -struct no_result - : std::true_type -{}; - -template -struct no_result::type> - : std::false_type -{}; - -struct C {}; -struct D : C {}; - -template -struct smart_ptr -{ - T& operator*() const noexcept(IsNothrow); -}; - -template -struct conv_to -{ - operator T() const noexcept(IsNothrow); -}; - -int main() -{ - /* mem-fun-ptr */ { - using Fn = int (C::*)(int); - - CHECK(std::is_same::type, int>::value); - CHECK(no_result>::value); - CHECK(std::is_same::type, int>::value); - CHECK(no_result>::value); - - CHECK(std::is_same::type, int>::value); - CHECK(no_result>::value); - CHECK(std::is_same::type, int>::value); - CHECK(no_result>::value); - - CHECK(std::is_same, int>::type, int>::value); - CHECK(no_result, int>>::value); - - CHECK(std::is_same::type, int>::value); - CHECK(no_result>::value); - - CHECK(std::is_same, int>::type, int>::value); - CHECK(no_result, int>>::value); - - CHECK(no_result>::value); - CHECK(no_result>::value); - CHECK(no_result>::value); - - using Fnc = int (C::*)(int) const; - - CHECK(std::is_same::type, int>::value); - CHECK(std::is_same::type, int>::value); - CHECK(std::is_same::type, int>::value); - CHECK(std::is_same::type, int>::value); - - using Fnl = int (C::*)(int)&; - - CHECK(std::is_same::type, int>::value); - CHECK(no_result>::value); - CHECK(no_result>::value); - CHECK(no_result>::value); - - using Fnr = int (C::*)(int)&&; - - CHECK(no_result>::value); - CHECK(no_result>::value); - CHECK(std::is_same::type, int>::value); - CHECK(no_result>::value); - - using Fncl = int (C::*)(int) const&; - - CHECK(std::is_same::type, int>::value); - CHECK(std::is_same::type, int>::value); -#if __cplusplus > 201703L || defined(_MSC_VER) // C++20: P0704 - CHECK(std::is_same::type, int>::value); - CHECK(std::is_same::type, int>::value); -#else - CHECK(no_result>::value); - CHECK(no_result>::value); -#endif - - using Fncr = int (C::*)(int) const&&; - - CHECK(no_result>::value); - CHECK(no_result>::value); - CHECK(std::is_same::type, int>::value); - CHECK(std::is_same::type, int>::value); - } - - /* mem-obj-ptr */ { - using Fn = int C::*; - - CHECK(std::is_same::type, int&>::value); - CHECK(std::is_same::type, int const&>::value); - CHECK(std::is_same::type, int&&>::value); - CHECK(std::is_same::type, int const&&>::value); - - CHECK(std::is_same::type, int&>::value); - CHECK(std::is_same::type, int const&>::value); - CHECK(std::is_same::type, int&&>::value); - CHECK(std::is_same::type, int const&&>::value); - - CHECK(std::is_same>::type, int&>::value); - CHECK(std::is_same>::type, int const&>::value); - - CHECK(std::is_same::type, int&>::value); - CHECK(std::is_same::type,int const&>::value); - - CHECK(std::is_same>::type, int&>::value); - CHECK(std::is_same>::type, int const&>::value); - - CHECK(no_result>::value); - CHECK(no_result>::value); - CHECK(no_result>::value); - } - - /* call-op */ { - struct Fn - { - int operator()(int); - }; - - CHECK(std::is_same::type, int>::value); - CHECK(no_result>::value); - CHECK(std::is_same::type, int>::value); - CHECK(no_result>::value); - - CHECK(no_result>::value); - CHECK(no_result>::value); - CHECK(no_result>::value); - - struct Fnc - { - int operator()(int) const; - }; - - CHECK(std::is_same::type, int>::value); - CHECK(std::is_same::type, int>::value); - CHECK(std::is_same::type, int>::value); - CHECK(std::is_same::type, int>::value); - - struct Fnl - { - int operator()(int) &; - }; - - CHECK(std::is_same::type, int>::value); - CHECK(no_result>::value); - CHECK(no_result>::value); - CHECK(no_result>::value); - - struct Fnr - { - int operator()(int) &&; - }; - - CHECK(no_result>::value); - CHECK(no_result>::value); - CHECK(std::is_same::type, int>::value); - CHECK(no_result>::value); - - struct Fncl - { - int operator()(int) const&; - }; - - CHECK(std::is_same::type, int>::value); - CHECK(std::is_same::type, int>::value); - CHECK(std::is_same::type, int>::value); - CHECK(std::is_same::type, int>::value); - - struct Fncr - { - int operator()(int) const&&; - }; - - CHECK(no_result>::value); - CHECK(no_result>::value); - CHECK(std::is_same::type, int>::value); - CHECK(std::is_same::type, int>::value); - } - - /* fun-ptr */ { - using Fn_ptr = int (*)(int); - - CHECK(std::is_same::type, int>::value); - CHECK(std::is_same>::type, int>::value); - - CHECK(no_result>::value); - CHECK(no_result>::value); - } - - /* alias */ { - CHECK(std::is_same, - typename eggs::invoke_result::type>::value); - } - - return test_report(); -} diff --git a/test/is_invocable.cpp b/test/is_invocable.cpp deleted file mode 100644 index a546a10..0000000 --- a/test/is_invocable.cpp +++ /dev/null @@ -1,305 +0,0 @@ -// Eggs.Invoke -// -// Copyright Agustin K-ballo Berge, Fusion Fenix 2017-2020 -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#include - -#include -#include - -#include "test.hpp" - -// Account for P0012: "Make exception specifications be part of the type system". -static constexpr bool p0012 = !std::is_same::value; - -struct C -{ - int fun(int) noexcept(p0012) - { - return 0; - } - int cfun(int) const noexcept(p0012) - { - return 1; - } - int lfun(int) & noexcept(p0012) - { - return 2; - } - int rfun(int) && noexcept(p0012) - { - return 3; - } - int clfun(int) const& noexcept(p0012) - { - return 4; - } - int crfun(int) const&& noexcept(p0012) - { - return 5; - } -}; - -struct D : C {}; - -template -struct smart_ptr -{ - T* ptr; - T& operator*() const noexcept(IsNothrow); -}; -template -using smart_ptr_throws = smart_ptr; - -template -struct conv_to -{ - operator T() const noexcept(IsNothrow); -}; -template -using conv_to_throws = conv_to; - -template -struct conv_from -{ - conv_from(T) noexcept(IsNothrow) {} -}; -template -using conv_from_throws = conv_from; - -std::true_type const nothrows{}; -std::false_type const throws{}; -std::integral_constant const p0012_nothrows{}; - -template -void test_invocable(std::integral_constant, - std::integral_constant = {}) -{ - CHECK(std::is_base_of>::value); - CHECK(std::is_base_of>::value); - CHECK(std::is_base_of>::value); - CHECK(std::is_base_of>::value); - - CHECK(std::is_base_of, - eggs::is_nothrow_invocable>::value); - CHECK(std::is_base_of, - eggs::is_nothrow_invocable_r>::value); - CHECK(std::is_base_of, - eggs::is_nothrow_invocable_r>::value); - CHECK(std::is_base_of, - eggs::is_nothrow_invocable_r>::value); -} - -template -void test_not_invocable() -{ - CHECK(std::is_base_of>::value); - CHECK(std::is_base_of>::value); - CHECK(std::is_base_of>::value); - - CHECK(std::is_base_of>::value); - CHECK(std::is_base_of>::value); - CHECK(std::is_base_of>::value); -} - -int main() -{ - /* mem-fun-ptr */ { - using Fn = decltype(&C::fun); - - CHECK_SCOPE(test_invocable(p0012_nothrows)); - CHECK_SCOPE(test_not_invocable()); - CHECK_SCOPE(test_invocable(p0012_nothrows)); - CHECK_SCOPE(test_not_invocable()); - - CHECK_SCOPE(test_invocable(p0012_nothrows)); - CHECK_SCOPE(test_not_invocable()); - CHECK_SCOPE(test_invocable(p0012_nothrows)); - CHECK_SCOPE(test_not_invocable()); - - CHECK_SCOPE(test_invocable, int>(p0012_nothrows)); - CHECK_SCOPE(test_not_invocable, int>()); - - CHECK_SCOPE(test_invocable(p0012_nothrows)); - CHECK_SCOPE(test_not_invocable()); - - CHECK_SCOPE(test_invocable, int>(p0012_nothrows)); - CHECK_SCOPE(test_not_invocable, int>()); - - CHECK_SCOPE(test_invocable, int>(throws)); - CHECK_SCOPE(test_not_invocable, int>()); - - CHECK_SCOPE(test_not_invocable()); - CHECK_SCOPE(test_not_invocable()); - CHECK_SCOPE(test_not_invocable()); - - using Fnc = decltype(&C::cfun); - - CHECK_SCOPE(test_invocable(p0012_nothrows)); - CHECK_SCOPE(test_invocable(p0012_nothrows)); - CHECK_SCOPE(test_invocable(p0012_nothrows)); - CHECK_SCOPE(test_invocable(p0012_nothrows)); - - using Fnl = decltype(&C::lfun); - - CHECK_SCOPE(test_invocable(p0012_nothrows)); - CHECK_SCOPE(test_not_invocable()); - CHECK_SCOPE(test_not_invocable()); - CHECK_SCOPE(test_not_invocable()); - - using Fnr = decltype(&C::rfun); - - CHECK_SCOPE(test_not_invocable()); - CHECK_SCOPE(test_not_invocable()); - CHECK_SCOPE(test_invocable(p0012_nothrows)); - CHECK_SCOPE(test_not_invocable()); - - using Fncl = decltype(&C::clfun); - - CHECK_SCOPE(test_invocable(p0012_nothrows)); - CHECK_SCOPE(test_invocable(p0012_nothrows)); -#if __cplusplus > 201703L || defined(_MSC_VER) // C++20: P0704 - CHECK_SCOPE(test_invocable(p0012_nothrows)); - CHECK_SCOPE(test_invocable(p0012_nothrows)); -#else - CHECK_SCOPE(test_not_invocable()); - CHECK_SCOPE(test_not_invocable()); -#endif - - using Fncr = decltype(&C::crfun); - - CHECK_SCOPE(test_not_invocable()); - CHECK_SCOPE(test_not_invocable()); - CHECK_SCOPE(test_invocable(p0012_nothrows)); - CHECK_SCOPE(test_invocable(p0012_nothrows)); - } - - /* mem-obj-ptr */ { - using Fn = int C::*; - - CHECK_SCOPE(test_invocable(nothrows)); - CHECK_SCOPE(test_invocable(nothrows)); - CHECK_SCOPE(test_invocable(nothrows)); - CHECK_SCOPE(test_invocable(nothrows)); - - CHECK_SCOPE(test_invocable(nothrows)); - CHECK_SCOPE(test_invocable(nothrows)); - CHECK_SCOPE(test_invocable(nothrows)); - CHECK_SCOPE(test_invocable(nothrows)); - - CHECK_SCOPE(test_invocable>(nothrows)); - CHECK_SCOPE(test_invocable>(nothrows)); - - CHECK_SCOPE(test_invocable(nothrows)); - CHECK_SCOPE(test_invocable(nothrows)); - - CHECK_SCOPE(test_invocable>(nothrows)); - CHECK_SCOPE(test_invocable>(nothrows)); - - CHECK_SCOPE(test_invocable>(throws)); - CHECK_SCOPE(test_invocable>(throws)); - - CHECK_SCOPE(test_not_invocable()); - CHECK_SCOPE(test_not_invocable()); - CHECK_SCOPE(test_not_invocable()); - } - - /* call-op */ { - struct Fn - { - int operator()(int) noexcept(p0012); - }; - - CHECK_SCOPE(test_invocable(p0012_nothrows)); - CHECK_SCOPE(test_not_invocable()); - CHECK_SCOPE(test_invocable(p0012_nothrows)); - CHECK_SCOPE(test_not_invocable()); - - CHECK_SCOPE(test_not_invocable()); - CHECK_SCOPE(test_not_invocable()); - CHECK_SCOPE(test_not_invocable()); - - struct Fnc - { - int operator()(int) const noexcept(p0012); - }; - - CHECK_SCOPE(test_invocable(p0012_nothrows)); - CHECK_SCOPE(test_invocable(p0012_nothrows)); - CHECK_SCOPE(test_invocable(p0012_nothrows)); - CHECK_SCOPE(test_invocable(p0012_nothrows)); - - struct Fnl - { - int operator()(int) & noexcept(p0012); - }; - - CHECK_SCOPE(test_invocable(p0012_nothrows)); - CHECK_SCOPE(test_not_invocable()); - CHECK_SCOPE(test_not_invocable()); - CHECK_SCOPE(test_not_invocable()); - - struct Fnr - { - int operator()(int) && noexcept(p0012); - }; - - CHECK_SCOPE(test_not_invocable()); - CHECK_SCOPE(test_not_invocable()); - CHECK_SCOPE(test_invocable(p0012_nothrows)); - CHECK_SCOPE(test_not_invocable()); - - struct Fncl - { - int operator()(int) const& noexcept(p0012); - }; - - CHECK_SCOPE(test_invocable(p0012_nothrows)); - CHECK_SCOPE(test_invocable(p0012_nothrows)); - CHECK_SCOPE(test_invocable(p0012_nothrows)); - CHECK_SCOPE(test_invocable(p0012_nothrows)); - - struct Fncr - { - int operator()(int) const&& noexcept(p0012); - }; - - CHECK_SCOPE(test_not_invocable()); - CHECK_SCOPE(test_not_invocable()); - CHECK_SCOPE(test_invocable(p0012_nothrows)); - CHECK_SCOPE(test_invocable(p0012_nothrows)); - } - - /* fun-ptr */ { - struct Fn - { - static int fun(int) noexcept(p0012); - }; - using Fn_ptr = decltype(&Fn::fun); - - CHECK_SCOPE(test_invocable(p0012_nothrows)); - CHECK_SCOPE(test_invocable>(p0012_nothrows)); - CHECK_SCOPE(test_invocable>(throws)); - CHECK_SCOPE(test_invocable, Fn_ptr, int>(p0012_nothrows, p0012_nothrows)); - CHECK_SCOPE(test_invocable, Fn_ptr, int>(p0012_nothrows, throws)); - - CHECK_SCOPE(test_not_invocable()); - CHECK_SCOPE(test_not_invocable()); - } - - return test_report(); -} diff --git a/test/macro.cpp b/test/macro.cpp deleted file mode 100644 index a7592f3..0000000 --- a/test/macro.cpp +++ /dev/null @@ -1,385 +0,0 @@ -// Eggs.Invoke -// -// Copyright Agustin K-ballo Berge, Fusion Fenix 2017-2020 -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#include - -#include -#include - -#include "test.hpp" - -#if __cpp_constexpr >= 201304 -#define constexpr14 constexpr -#define CHECK_CONSTEXPR14 CHECK_CONSTEXPR -#else -#define constexpr14 -#define CHECK_CONSTEXPR14 -#endif - -#if __cplusplus >= 202002L && __cpp_lib_constexpr_functional >= 201907L -#define constexpr20 constexpr -#define CHECK_CONSTEXPR20 CHECK_CONSTEXPR -#else -#define constexpr20 -#define CHECK_CONSTEXPR20 -#endif - -// Account for P0012: "Make exception specifications be part of the type system". -static constexpr bool p0012 = !std::is_same::value; - -struct C -{ - int obj; - - constexpr C(int val) - : obj(val) - {} - - constexpr14 int fun(int base) noexcept(p0012) - { - return base + 0; - } - constexpr int cfun(int base) const noexcept(p0012) - { - return base + 1; - } - constexpr14 int lfun(int base) & noexcept(p0012) - { - return base + 2; - } - constexpr14 int rfun(int base) && noexcept(p0012) - { - return base + 3; - } - constexpr int clfun(int base) const& noexcept(p0012) - { - return base + 4; - } - constexpr int crfun(int base) const&& noexcept(p0012) - { - return base + 5; - } -}; - -struct D : C -{ - constexpr D(int val) : C(val) - {} -}; - -template -struct smart_ptr -{ - T* ptr; - constexpr smart_ptr(T* ptr) : ptr(ptr) {} - constexpr T& operator*() const noexcept(IsNothrow) { return *ptr; } -}; -template -using smart_ptr_throws = smart_ptr; - -template -struct conv_to -{ - T val; - constexpr operator T() const noexcept(IsNothrow) { return val; } - constexpr bool operator==(conv_to const& other) const noexcept { return val == other.val; } -}; -template -using conv_to_throws = conv_to; - -template -struct conv_from -{ - T val; - constexpr conv_from(T val) noexcept(IsNothrow) : val(val) {} - constexpr bool operator==(conv_from const& other) const noexcept { return val == other.val; } -}; -template -using conv_from_throws = conv_from; - -void test_mem_obj_ptr() -{ - constexpr auto obj = &C::obj; - - /* reference */ { - static C x = {42}; - constexpr C& r = x; - constexpr C const& cr = x; - - EGGS_INVOKE(obj, r); - EGGS_INVOKE(obj, cr); - EGGS_INVOKE(obj, std::move(r)); - EGGS_INVOKE(obj, std::move(cr)); - - static D d = {42}; - constexpr D& rd = d; - constexpr D const& crd = d; - - EGGS_INVOKE(obj, rd); - EGGS_INVOKE(obj, crd); - EGGS_INVOKE(obj, std::move(rd)); - EGGS_INVOKE(obj, std::move(crd)); - } - - /* reference wrapper */ { - static C x = {42}; - constexpr20 std::reference_wrapper r = x; - constexpr20 std::reference_wrapper cr = x; - - EGGS_INVOKE(obj, r); - EGGS_INVOKE(obj, cr); - } - - /* pointer */ { - static C x = {42}; - constexpr C* p = &x; - constexpr C const* cp = &x; - - EGGS_INVOKE(obj, p); - EGGS_INVOKE(obj, cp); - } - - /* smart pointer */ { - static C x = {42}; - constexpr smart_ptr p = &x; - constexpr smart_ptr cp = &x; - - EGGS_INVOKE(obj, p); - EGGS_INVOKE(obj, cp); - - constexpr smart_ptr_throws tp = &x; - constexpr smart_ptr_throws tcp = &x; - - EGGS_INVOKE(obj, tp); - EGGS_INVOKE(obj, tcp); - } -} - -void test_mem_fun_ptr() -{ - constexpr auto fun = &C::fun; - constexpr auto cfun = &C::cfun; - constexpr auto lfun = &C::lfun; - constexpr auto rfun = &C::rfun; - constexpr auto clfun = &C::clfun; - constexpr auto crfun = &C::crfun; - - /* reference */ { - static C x = {42}; - constexpr C& r = x; - constexpr C const& cr = x; - - EGGS_INVOKE(fun, r, 40); - EGGS_INVOKE(cfun, r, 40); - EGGS_INVOKE(lfun, r, 40); - EGGS_INVOKE(clfun, r, 40); - - EGGS_INVOKE(cfun, cr, 40); - EGGS_INVOKE(clfun, cr, 40); - - EGGS_INVOKE(fun, std::move(r), 40); - EGGS_INVOKE(cfun, std::move(r), 40); -#if __cplusplus > 201703L || defined(_MSC_VER) // C++20: P0704 - EGGS_INVOKE(clfun, std::move(r), 40); -#else -#endif - EGGS_INVOKE(rfun, std::move(r), 40); - EGGS_INVOKE(crfun, std::move(r), 40); - - EGGS_INVOKE(cfun, std::move(cr), 40); -#if __cplusplus > 201703L || defined(_MSC_VER) // C++20: P0704 - EGGS_INVOKE(clfun, std::move(cr), 40); -#else -#endif - EGGS_INVOKE(crfun, std::move(cr), 40); - } - - /* reference wrapper */ { - static C x = {42}; - constexpr20 std::reference_wrapper r = x; - constexpr20 std::reference_wrapper cr = x; - - EGGS_INVOKE(fun, r, 40); - EGGS_INVOKE(cfun, r, 40); - EGGS_INVOKE(lfun, r, 40); - EGGS_INVOKE(clfun, r, 40); - - EGGS_INVOKE(cfun, cr, 40); - EGGS_INVOKE(clfun, cr, 40); - } - - /* pointer */ { - static C x = {42}; - constexpr C* p = &x; - constexpr C const* cp = &x; - - EGGS_INVOKE(fun, p, 40); - EGGS_INVOKE(cfun, p, 40); - EGGS_INVOKE(lfun, p, 40); - EGGS_INVOKE(clfun, p, 40); - - EGGS_INVOKE(cfun, cp, 40); - EGGS_INVOKE(clfun, cp, 40); - } - - /* smart pointer */ { - static C x = {42}; - constexpr smart_ptr p = &x; - constexpr smart_ptr cp = &x; - - EGGS_INVOKE(fun, p, 40); - EGGS_INVOKE(cfun, p, 40); - EGGS_INVOKE(lfun, p, 40); - EGGS_INVOKE(clfun, p, 40); - - EGGS_INVOKE(cfun, cp, 40); - EGGS_INVOKE(clfun, cp, 40); - - constexpr smart_ptr_throws tp = &x; - constexpr smart_ptr_throws tcp = &x; - - EGGS_INVOKE(fun, tp, 40); - EGGS_INVOKE(cfun, tp, 40); - EGGS_INVOKE(lfun, tp, 40); - EGGS_INVOKE(clfun, tp, 40); - - EGGS_INVOKE(cfun, tcp, 40); - EGGS_INVOKE(clfun, tcp, 40); - } -} - -void test_fun_obj() -{ - /* call-op */ { - struct Fn - { - constexpr14 int operator()(int base) noexcept - { - return base + 0; - } - }; - auto f = Fn{}; - //constexpr auto cf = Fn{}; - - EGGS_INVOKE(f, 40); - EGGS_INVOKE(std::move(f), 40); - - struct Fnc - { - constexpr int operator()(int base) const noexcept - { - return base + 1; - } - }; - auto fc = Fnc{}; - constexpr auto cfc = Fnc{}; - - EGGS_INVOKE(fc, 40); - EGGS_INVOKE(cfc, 40); - EGGS_INVOKE(std::move(fc), 40); - EGGS_INVOKE(std::move(cfc), 40); - - struct Fnl - { - constexpr14 int operator()(int base) & noexcept - { - return base + 2; - } - }; - auto fl = Fnl{}; - //constexpr auto cfl = Fnl{}; - - EGGS_INVOKE(fl, 40); - - struct Fnr - { - constexpr14 int operator()(int base) && noexcept - { - return base + 3; - } - }; - auto fr = Fnr{}; - //constexpr auto cfr = Fnr{}; - - EGGS_INVOKE(std::move(fr), 40); - - struct Fncl - { - constexpr int operator()(int base) const& noexcept - { - return base + 4; - } - }; - auto fcl = Fncl{}; - constexpr auto cfcl = Fncl{}; - - EGGS_INVOKE(fcl, 40); - EGGS_INVOKE(cfcl, 40); - EGGS_INVOKE(std::move(fcl), 40); - EGGS_INVOKE(std::move(cfcl), 40); - - struct Fncr - { - constexpr int operator()(int base) const&& noexcept - { - return base + 5; - } - }; - auto fcr = Fncr{}; - constexpr auto cfcr = Fncr{}; - - EGGS_INVOKE(std::move(fcr), 40); - EGGS_INVOKE(std::move(cfcr), 40); - } - - /* fun-ptr */ { - struct S - { - static constexpr int f(int base) noexcept(p0012) - { - return base + 6; - } - }; - constexpr auto f = &S::f; - - EGGS_INVOKE(f, 40); - EGGS_INVOKE_R(int, f, 40); - - EGGS_INVOKE(f, conv_to{40}); - EGGS_INVOKE(f, conv_to_throws{40}); - EGGS_INVOKE_R(conv_from, f, 40); - EGGS_INVOKE_R(conv_from_throws, f, 40); - } - - /* fun-ref */ { - struct S - { - static constexpr int f0() noexcept(p0012) - { - return 6; - } - static constexpr int f1(int base) noexcept(p0012) - { - return base + 6; - } - }; - - EGGS_INVOKE(S::f0); - EGGS_INVOKE_R(int, S::f0); - EGGS_INVOKE(S::f1, 40); - EGGS_INVOKE_R(int, S::f1, 40); - } -} - -int main() -{ - test_mem_obj_ptr(); - test_mem_fun_ptr(); - test_fun_obj(); - - return test_report(); -} diff --git a/test/test.hpp b/test/test.hpp deleted file mode 100644 index 6015999..0000000 --- a/test/test.hpp +++ /dev/null @@ -1,107 +0,0 @@ -// Eggs.Invoke -// -// Copyright Agustin K-ballo Berge, Fusion Fenix 2020 -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#ifndef TEST_HPP -#define TEST_HPP - -#include -#include -#include - -/////////////////////////////////////////////////////////////////////////////// -struct test_context -{ - char const* file; - unsigned line; - char const* expr; -}; - -inline std::ostream& operator<<(std::ostream& out, test_context const& context) -{ - return out << context.file << "(" << context.line << "): " << context.expr; -} - -/////////////////////////////////////////////////////////////////////////////// -template -struct test_scope_stack -{ - static std::deque stack; -}; - -template -std::deque test_scope_stack<_>::stack; - -struct test_scope : test_scope_stack<> -{ - explicit test_scope(test_context const& context) - { - stack.push_front(context); - } - - ~test_scope() - { - stack.pop_front(); - } -}; - -/////////////////////////////////////////////////////////////////////////////// -template -struct test_report_info -{ - static unsigned checks; - static unsigned failures; -}; - -template -unsigned test_report_info<_>::checks = 0; -template -unsigned test_report_info<_>::failures = 0; - -inline void test_check(bool c, test_context context) -{ - ++test_report_info<>::checks; - if (!c) - { - ++test_report_info<>::failures; - - std::cerr << context << " is false\n"; - for (auto const& scope : test_scope::stack) - std::cerr << " " << scope << '\n'; - std::cerr << '\n'; - } -} - -inline int test_report() -{ - unsigned const checks = test_report_info<>::checks; - unsigned const failures = test_report_info<>::failures; - if (failures) - { - std::cout << failures << " out of " << checks << " checks failed.\n"; - return EXIT_FAILURE; - } else { - std::cout << "All " << checks << " checks succeeded.\n"; - return EXIT_SUCCESS; - } -} - -/////////////////////////////////////////////////////////////////////////////// -#define PP_CONCAT_I(A, B) A##B -#define PP_CONCAT(A, B) PP_CONCAT_I(A, B) -#define PP_UNIQUE(PREFIX) PP_CONCAT(PREFIX##_, __LINE__) - -#define CHECK(...) \ - (::test_check((__VA_ARGS__), {__FILE__, __LINE__, #__VA_ARGS__})) - -#define CHECK_CONSTEXPR(...) \ - constexpr decltype((__VA_ARGS__)) PP_UNIQUE(constexpr) = (__VA_ARGS__); \ - CHECK(PP_UNIQUE(constexpr) == (__VA_ARGS__)) - -#define CHECK_SCOPE(...) \ - (::test_scope{{__FILE__, __LINE__, #__VA_ARGS__}}, (__VA_ARGS__)) - -#endif /*TEST_HPP*/ diff --git a/tools/extract_data.py b/tools/extract_data.py new file mode 100644 index 0000000..106099d --- /dev/null +++ b/tools/extract_data.py @@ -0,0 +1,56 @@ +# Eggs.Invoke +# +# Copyright Agustin K-ballo Berge, Fusion Fenix 2020 +# +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +import glob +import itertools +import json +import re + +def overhead(aspect, values, baseline): + value = float(values[aspect]) + base = float(baseline[aspect]) + return (value, value / base - 1.0) + +if __name__ == '__main__': + table = [] + for filename in glob.glob("benchmark.*.json"): + with open(filename) as file: + benchmark = json.load(file) + + template = re.match('^benchmark.([a-zA-Z_]+).json$', filename).group(1) + for values in benchmark['values']: + values['memory_usage'] = values['memory_usage'] / 1024.0 / 1024.0 + values['object_size'] = values['object_size'] / 1024.0 / 1024.0 + + row = {} + row['benchmark'] = template + row['index'] = values['benchmark'] + row['case'] = values['label'] + row['compilation_time'] = values['compilation_time'] + row['memory_usage'] = values['memory_usage'] + row['object_size'] = values['object_size'] + table.append(row) + + results = [] + benchmark = lambda x: x['benchmark'] + table.sort(key=benchmark) + grouped = itertools.groupby(table, key=benchmark) + for key, group in grouped: + values = list(group) + for e in values: + del e['benchmark'] + if e['index'] == 1: + baseline = e + del e['index'] + values.remove(baseline) + + result = {} + result['benchmark'] = key + result['godbolt'] = 'https://godbolt.org/z/' + result['baseline'] = baseline + result['values'] = values + results.append(result) + print(json.dumps(results, sort_keys=True) + ',')