From 61a76715a8cf71ced73a0c38b1f4dc1591eebe6e Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Sat, 28 Dec 2019 12:15:29 +0700 Subject: [PATCH 1/3] to C++17, remove custom invoke impl --- CMakeLists.txt | 4 +- headers/promise.hpp/invoke.hpp | 248 --------------- headers/promise.hpp/jobber.hpp | 22 +- headers/promise.hpp/promise.hpp | 65 ++-- headers/promise.hpp/scheduler.hpp | 21 +- untests/invoke_tests.cpp | 510 ------------------------------ 6 files changed, 40 insertions(+), 830 deletions(-) delete mode 100644 headers/promise.hpp/invoke.hpp delete mode 100644 untests/invoke_tests.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 41999ff..af1f48d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -# 3.8 version is required for `cxx_std_14` +# 3.8 version is required for `cxx_std_17` cmake_minimum_required(VERSION 3.8 FATAL_ERROR) if(NOT DEFINED PROJECT_NAME) @@ -9,7 +9,7 @@ project(promise.hpp) add_library(${PROJECT_NAME} INTERFACE) target_include_directories(${PROJECT_NAME} INTERFACE headers) -target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_14) +target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_17) if(BUILD_AS_STANDALONE) option(BUILD_WITH_UNTESTS "Build with unit tests" ON) diff --git a/headers/promise.hpp/invoke.hpp b/headers/promise.hpp/invoke.hpp deleted file mode 100644 index b75657f..0000000 --- a/headers/promise.hpp/invoke.hpp +++ /dev/null @@ -1,248 +0,0 @@ -/******************************************************************************* - * This file is part of the "https://github.com/blackmatov/invoke.hpp" - * For conditions of distribution and use, see copyright notice in LICENSE.md - * Copyright (C) 2018-2019, by Matvey Cherevko (blackmatov@gmail.com) - ******************************************************************************/ - -#pragma once - -#include -#include -#include -#include - -#define INVOKE_HPP_NOEXCEPT_RETURN(...) \ - noexcept(noexcept(__VA_ARGS__)) { return __VA_ARGS__; } - -#define INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN(...) \ - noexcept(noexcept(__VA_ARGS__)) -> decltype (__VA_ARGS__) { return __VA_ARGS__; } - -// -// void_t -// - -namespace invoke_hpp -{ - namespace impl - { - template < typename... Args > - struct make_void { - using type = void; - }; - } - - template < typename... Args > - using void_t = typename impl::make_void::type; -} - -// -// is_reference_wrapper -// - -namespace invoke_hpp -{ - namespace impl - { - template < typename T > - struct is_reference_wrapper_impl - : std::false_type {}; - - template < typename U > - struct is_reference_wrapper_impl> - : std::true_type {}; - } - - template < typename T > - struct is_reference_wrapper - : impl::is_reference_wrapper_impl> {}; -} - -// -// invoke -// - -namespace invoke_hpp -{ - namespace impl - { - // - // invoke_member_object_impl - // - - template - < - typename Base, typename F, typename Derived, - typename std::enable_if_t>::value, int> = 0 - > - constexpr auto invoke_member_object_impl(F Base::* f, Derived&& ref) - INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN( - std::forward(ref).*f) - - template - < - typename Base, typename F, typename RefWrap, - typename std::enable_if_t>::value, int> = 0 - > - constexpr auto invoke_member_object_impl(F Base::* f, RefWrap&& ref) - INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN( - ref.get().*f) - - template - < - typename Base, typename F, typename Pointer, - typename std::enable_if_t< - !std::is_base_of>::value && - !is_reference_wrapper>::value - , int> = 0 - > - constexpr auto invoke_member_object_impl(F Base::* f, Pointer&& ptr) - INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN( - (*std::forward(ptr)).*f) - - // - // invoke_member_function_impl - // - - template - < - typename Base, typename F, typename Derived, typename... Args, - typename std::enable_if_t>::value, int> = 0 - > - constexpr auto invoke_member_function_impl(F Base::* f, Derived&& ref, Args&&... args) - INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN( - (std::forward(ref).*f)(std::forward(args)...)) - - template - < - typename Base, typename F, typename RefWrap, typename... Args, - typename std::enable_if_t>::value, int> = 0 - > - constexpr auto invoke_member_function_impl(F Base::* f, RefWrap&& ref, Args&&... args) - INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN( - (ref.get().*f)(std::forward(args)...)) - - template - < - typename Base, typename F, typename Pointer, typename... Args, - typename std::enable_if_t< - !std::is_base_of>::value && - !is_reference_wrapper>::value - , int> = 0 - > - constexpr auto invoke_member_function_impl(F Base::* f, Pointer&& ptr, Args&&... args) - INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN( - ((*std::forward(ptr)).*f)(std::forward(args)...)) - } - - template - < - typename F, typename... Args, - typename std::enable_if_t>::value, int> = 0 - > - constexpr auto invoke(F&& f, Args&&... args) - INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN( - std::forward(f)(std::forward(args)...)) - - template - < - typename F, typename T, - typename std::enable_if_t>::value, int> = 0 - > - constexpr auto invoke(F&& f, T&& t) - INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN( - impl::invoke_member_object_impl(std::forward(f), std::forward(t))) - - template - < - typename F, typename... Args, - typename std::enable_if_t>::value, int> = 0 - > - constexpr auto invoke(F&& f, Args&&... args) - INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN( - impl::invoke_member_function_impl(std::forward(f), std::forward(args)...)) -} - -// -// invoke_result -// - -namespace invoke_hpp -{ - namespace impl - { - struct invoke_result_impl_tag {}; - - template < typename Void, typename F, typename... Args > - struct invoke_result_impl {}; - - template < typename F, typename... Args > - struct invoke_result_impl(), std::declval()...))>, F, Args...> { - using type = decltype(invoke_hpp::invoke(std::declval(), std::declval()...)); - }; - } - - template < typename F, typename... Args > - struct invoke_result - : impl::invoke_result_impl {}; - - template < typename F, typename... Args > - using invoke_result_t = typename invoke_result::type; -} - -// -// is_invocable -// - -namespace invoke_hpp -{ - namespace impl - { - struct is_invocable_r_impl_tag {}; - - template < typename Void, typename R, typename F, typename... Args > - struct is_invocable_r_impl - : std::false_type {}; - - template < typename R, typename F, typename... Args > - struct is_invocable_r_impl>, R, F, Args...> - : std::conditional_t< - std::is_void::value, - std::true_type, - std::is_convertible, R>> {}; - } - - template < typename R, typename F, typename... Args > - struct is_invocable_r - : impl::is_invocable_r_impl {}; - - template < typename F, typename... Args > - using is_invocable = is_invocable_r; -} - -// -// apply -// - -namespace invoke_hpp -{ - namespace impl - { - template < typename F, typename Tuple, std::size_t... I > - constexpr decltype(auto) apply_impl(F&& f, Tuple&& args, std::index_sequence) - INVOKE_HPP_NOEXCEPT_RETURN( - invoke_hpp::invoke( - std::forward(f), - std::get(std::forward(args))...)) - } - - template < typename F, typename Tuple > - constexpr decltype(auto) apply(F&& f, Tuple&& args) - INVOKE_HPP_NOEXCEPT_RETURN( - impl::apply_impl( - std::forward(f), - std::forward(args), - std::make_index_sequence>::value>())) -} - -#undef INVOKE_HPP_NOEXCEPT_RETURN -#undef INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN diff --git a/headers/promise.hpp/jobber.hpp b/headers/promise.hpp/jobber.hpp index 958f850..a398aca 100644 --- a/headers/promise.hpp/jobber.hpp +++ b/headers/promise.hpp/jobber.hpp @@ -6,22 +6,6 @@ #pragma once -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - #include "promise.hpp" namespace jobber_hpp @@ -58,7 +42,7 @@ namespace jobber_hpp std::size_t>; template < typename F, typename... Args > - using async_invoke_result_t = invoke_hpp::invoke_result_t< + using async_invoke_result_t = std::invoke_result_t< std::decay_t, std::decay_t...>; @@ -378,7 +362,7 @@ namespace jobber_hpp template < typename R, typename F, typename... Args > void jobber::concrete_task::run() noexcept { try { - R value = invoke_hpp::apply(std::move(f_), std::move(args_)); + R value = std::apply(std::move(f_), std::move(args_)); promise_.resolve(std::move(value)); } catch (...) { promise_.reject(std::current_exception()); @@ -408,7 +392,7 @@ namespace jobber_hpp template < typename F, typename... Args > void jobber::concrete_task::run() noexcept { try { - invoke_hpp::apply(std::move(f_), std::move(args_)); + std::apply(std::move(f_), std::move(args_)); promise_.resolve(); } catch (...) { promise_.reject(std::current_exception()); diff --git a/headers/promise.hpp/promise.hpp b/headers/promise.hpp/promise.hpp index cfa51d8..64cc29f 100644 --- a/headers/promise.hpp/promise.hpp +++ b/headers/promise.hpp/promise.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -24,8 +25,6 @@ #include #include -#include "invoke.hpp" - namespace promise_hpp { // @@ -180,7 +179,7 @@ namespace promise_hpp } template < typename ResolveF - , typename ResolveFR = invoke_hpp::invoke_result_t > + , typename ResolveFR = std::invoke_result_t > std::enable_if_t< is_promise::value && std::is_void::value, promise> @@ -191,7 +190,7 @@ namespace promise_hpp n = next, f = std::forward(on_resolve) ](auto&& v) mutable { - auto np = invoke_hpp::invoke( + auto np = std::invoke( std::forward(f), std::forward(v)); std::move(np).then([n]() mutable { @@ -207,7 +206,7 @@ namespace promise_hpp } template < typename ResolveF - , typename ResolveFR = invoke_hpp::invoke_result_t > + , typename ResolveFR = std::invoke_result_t > std::enable_if_t< is_promise::value && !std::is_void::value, promise> @@ -218,7 +217,7 @@ namespace promise_hpp n = next, f = std::forward(on_resolve) ](auto&& v) mutable { - auto np = invoke_hpp::invoke( + auto np = std::invoke( std::forward(f), std::forward(v)); std::move(np).then([n](auto&& nv) mutable { @@ -238,7 +237,7 @@ namespace promise_hpp return then([ f = std::forward(on_resolve) ](auto&& v) mutable { - auto r = invoke_hpp::invoke( + auto r = std::invoke( std::forward(f), std::forward(v)); return make_all_promise(std::move(r)); @@ -250,7 +249,7 @@ namespace promise_hpp return then([ f = std::forward(on_resolve) ](auto&& v) mutable { - auto r = invoke_hpp::invoke( + auto r = std::invoke( std::forward(f), std::forward(v)); return make_race_promise(std::move(r)); @@ -262,7 +261,7 @@ namespace promise_hpp return then([ f = std::forward(on_resolve) ](auto&& v) mutable { - auto r = invoke_hpp::invoke( + auto r = std::invoke( std::forward(f), std::forward(v)); return make_tuple_promise(std::move(r)); @@ -271,7 +270,7 @@ namespace promise_hpp template < typename ResolveF , typename RejectF - , typename ResolveFR = invoke_hpp::invoke_result_t > + , typename ResolveFR = std::invoke_result_t > std::enable_if_t< !is_promise::value, promise> @@ -286,7 +285,7 @@ namespace promise_hpp } template < typename ResolveF - , typename ResolveFR = invoke_hpp::invoke_result_t > + , typename ResolveFR = std::invoke_result_t > std::enable_if_t< !is_promise::value, promise> @@ -443,7 +442,7 @@ namespace promise_hpp ](std::exception_ptr e) mutable { if ( has_reject ) { try { - invoke_hpp::invoke( + std::invoke( std::forward(f), e); n.resolve(); @@ -460,7 +459,7 @@ namespace promise_hpp f = std::forward(on_resolve) ](auto&& v) mutable { try { - invoke_hpp::invoke( + std::invoke( std::forward(f), std::forward(v)); n.resolve(); @@ -488,7 +487,7 @@ namespace promise_hpp ](std::exception_ptr e) mutable { if ( has_reject ) { try { - auto r = invoke_hpp::invoke( + auto r = std::invoke( std::forward(f), e); n.resolve(std::move(r)); @@ -505,7 +504,7 @@ namespace promise_hpp f = std::forward(on_resolve) ](auto&& v) mutable { try { - auto r = invoke_hpp::invoke( + auto r = std::invoke( std::forward(f), std::forward(v)); n.resolve(std::move(r)); @@ -521,11 +520,11 @@ namespace promise_hpp template < typename ResolveF, typename RejectF > void add_handlers_(ResolveF&& resolve, RejectF&& reject) { if ( status_ == status::resolved ) { - invoke_hpp::invoke( + std::invoke( std::forward(resolve), storage_.value()); } else if ( status_ == status::rejected ) { - invoke_hpp::invoke( + std::invoke( std::forward(reject), exception_); } else { @@ -616,7 +615,7 @@ namespace promise_hpp } template < typename ResolveF - , typename ResolveFR = invoke_hpp::invoke_result_t > + , typename ResolveFR = std::invoke_result_t > std::enable_if_t< is_promise::value && std::is_void::value, promise> @@ -627,7 +626,7 @@ namespace promise_hpp n = next, f = std::forward(on_resolve) ]() mutable { - auto np = invoke_hpp::invoke( + auto np = std::invoke( std::forward(f)); std::move(np).then([n]() mutable { n.resolve(); @@ -642,7 +641,7 @@ namespace promise_hpp } template < typename ResolveF - , typename ResolveFR = invoke_hpp::invoke_result_t > + , typename ResolveFR = std::invoke_result_t > std::enable_if_t< is_promise::value && !std::is_void::value, promise> @@ -653,7 +652,7 @@ namespace promise_hpp n = next, f = std::forward(on_resolve) ]() mutable { - auto np = invoke_hpp::invoke( + auto np = std::invoke( std::forward(f)); std::move(np).then([n](auto&& nv) mutable { n.resolve(std::forward(nv)); @@ -672,7 +671,7 @@ namespace promise_hpp return then([ f = std::forward(on_resolve) ]() mutable { - auto r = invoke_hpp::invoke( + auto r = std::invoke( std::forward(f)); return make_all_promise(std::move(r)); }); @@ -683,7 +682,7 @@ namespace promise_hpp return then([ f = std::forward(on_resolve) ]() mutable { - auto r = invoke_hpp::invoke( + auto r = std::invoke( std::forward(f)); return make_race_promise(std::move(r)); }); @@ -694,7 +693,7 @@ namespace promise_hpp return then([ f = std::forward(on_resolve) ]() mutable { - auto r = invoke_hpp::invoke( + auto r = std::invoke( std::forward(f)); return make_tuple_promise(std::move(r)); }); @@ -702,7 +701,7 @@ namespace promise_hpp template < typename ResolveF , typename RejectF - , typename ResolveFR = invoke_hpp::invoke_result_t > + , typename ResolveFR = std::invoke_result_t > std::enable_if_t< !is_promise::value, promise> @@ -717,7 +716,7 @@ namespace promise_hpp } template < typename ResolveF - , typename ResolveFR = invoke_hpp::invoke_result_t > + , typename ResolveFR = std::invoke_result_t > std::enable_if_t< !is_promise::value, promise> @@ -869,7 +868,7 @@ namespace promise_hpp ](std::exception_ptr e) mutable { if ( has_reject ) { try { - invoke_hpp::invoke( + std::invoke( std::forward(f), e); n.resolve(); @@ -886,7 +885,7 @@ namespace promise_hpp f = std::forward(on_resolve) ]() mutable { try { - invoke_hpp::invoke( + std::invoke( std::forward(f)); n.resolve(); } catch (...) { @@ -913,7 +912,7 @@ namespace promise_hpp ](std::exception_ptr e) mutable { if ( has_reject ) { try { - auto r = invoke_hpp::invoke( + auto r = std::invoke( std::forward(f), e); n.resolve(std::move(r)); @@ -930,7 +929,7 @@ namespace promise_hpp f = std::forward(on_resolve) ]() mutable { try { - auto r = invoke_hpp::invoke( + auto r = std::invoke( std::forward(f)); n.resolve(std::move(r)); } catch (...) { @@ -945,10 +944,10 @@ namespace promise_hpp template < typename ResolveF, typename RejectF > void add_handlers_(ResolveF&& resolve, RejectF&& reject) { if ( status_ == status::resolved ) { - invoke_hpp::invoke( + std::invoke( std::forward(resolve)); } else if ( status_ == status::rejected ) { - invoke_hpp::invoke( + std::invoke( std::forward(reject), exception_); } else { @@ -1032,7 +1031,7 @@ namespace promise_hpp }; try { - invoke_hpp::invoke( + std::invoke( std::forward(f), std::move(resolver), std::move(rejector)); diff --git a/headers/promise.hpp/scheduler.hpp b/headers/promise.hpp/scheduler.hpp index 93a17bf..7ace422 100644 --- a/headers/promise.hpp/scheduler.hpp +++ b/headers/promise.hpp/scheduler.hpp @@ -6,21 +6,6 @@ #pragma once -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - #include "promise.hpp" namespace scheduler_hpp @@ -57,7 +42,7 @@ namespace scheduler_hpp std::size_t>; template < typename F, typename... Args > - using schedule_invoke_result_t = invoke_hpp::invoke_result_t< + using schedule_invoke_result_t = std::invoke_result_t< std::decay_t, std::decay_t...>; @@ -286,7 +271,7 @@ namespace scheduler_hpp template < typename R, typename F, typename... Args > void scheduler::concrete_task::run() noexcept { try { - R value = invoke_hpp::apply(std::move(f_), std::move(args_)); + R value = std::apply(std::move(f_), std::move(args_)); promise_.resolve(std::move(value)); } catch (...) { promise_.reject(std::current_exception()); @@ -316,7 +301,7 @@ namespace scheduler_hpp template < typename F, typename... Args > void scheduler::concrete_task::run() noexcept { try { - invoke_hpp::apply(std::move(f_), std::move(args_)); + std::apply(std::move(f_), std::move(args_)); promise_.resolve(); } catch (...) { promise_.reject(std::current_exception()); diff --git a/untests/invoke_tests.cpp b/untests/invoke_tests.cpp deleted file mode 100644 index 0190028..0000000 --- a/untests/invoke_tests.cpp +++ /dev/null @@ -1,510 +0,0 @@ -/******************************************************************************* - * This file is part of the "https://github.com/blackmatov/invoke.hpp" - * For conditions of distribution and use, see copyright notice in LICENSE.md - * Copyright (C) 2018-2019, by Matvey Cherevko (blackmatov@gmail.com) - ******************************************************************************/ - -#define CATCH_CONFIG_FAST_COMPILE -#include - -#include -namespace inv = invoke_hpp; - -namespace -{ - void simple_static_function() { - } - - int simple_static_function_r() { - return 42; - } - - int simple_static_function_r_with_arg(int v) { - return v; - } - - const int& simple_static_function_r_with_ref_arg(const int& v) { - return v; - } - - class obj_t { - public: - int value = 42; - const int value_c = 42; - - void member() { - } - - int member_r() { - return 42; - } - - int member_r_with_arg(int v) { - return v; - } - - const int& member_r_with_ref_arg(const int& v) { - return v; - } - }; - - class obj2_t { - }; -} - -TEST_CASE("invoke"){ - SECTION("invoke_functions"){ - inv::invoke(simple_static_function); - REQUIRE(inv::invoke(simple_static_function_r) == 42); - REQUIRE(inv::invoke(simple_static_function_r_with_arg, 42) == 42); - { - int v = 42; - REQUIRE(&inv::invoke(simple_static_function_r_with_ref_arg, v) == &v); - } - } - SECTION("invoke_members"){ - obj_t o; - - inv::invoke(&obj_t::member, o); - inv::invoke(&obj_t::member, &o); - inv::invoke(&obj_t::member, std::ref(o)); - - REQUIRE(inv::invoke(&obj_t::member_r, o) == 42); - REQUIRE(inv::invoke(&obj_t::member_r, &o) == 42); - REQUIRE(inv::invoke(&obj_t::member_r, std::ref(o)) == 42); - - REQUIRE(inv::invoke(&obj_t::member_r_with_arg, o, 42) == 42); - REQUIRE(inv::invoke(&obj_t::member_r_with_arg, &o, 42) == 42); - REQUIRE(inv::invoke(&obj_t::member_r_with_arg, std::ref(o), 42) == 42); - - { - int v = 42; - REQUIRE(&inv::invoke(&obj_t::member_r_with_ref_arg, o, std::ref(v)) == &v); - REQUIRE(&inv::invoke(&obj_t::member_r_with_ref_arg, &o, std::ref(v)) == &v); - REQUIRE(&inv::invoke(&obj_t::member_r_with_ref_arg, std::ref(o), std::ref(v)) == &v); - } - } - SECTION("invoke_member_objects"){ - obj_t o; - - REQUIRE(inv::invoke(&obj_t::value, o) == 42); - REQUIRE(inv::invoke(&obj_t::value, &o) == 42); - REQUIRE(inv::invoke(&obj_t::value, std::ref(o)) == 42); - - REQUIRE(inv::invoke(&obj_t::value_c, o) == 42); - REQUIRE(inv::invoke(&obj_t::value_c, &o) == 42); - REQUIRE(inv::invoke(&obj_t::value_c, std::ref(o)) == 42); - } -} - -TEST_CASE("invoke_result"){ - SECTION("invoke_result_functions"){ - static_assert( - std::is_same< - void, - inv::invoke_result_t>::value, - "unit test fail"); - static_assert( - std::is_same< - int, - inv::invoke_result_t>::value, - "unit test fail"); - static_assert( - std::is_same< - int, - inv::invoke_result_t>::value, - "unit test fail"); - static_assert( - std::is_same< - const int&, - inv::invoke_result_t>::value, - "unit test fail"); - } - SECTION("invoke_result_members"){ - static_assert( - std::is_same>::value, - "unit test fail"); - static_assert( - std::is_same>::value, - "unit test fail"); - static_assert( - std::is_same>>::value, - "unit test fail"); - - static_assert( - std::is_same>::value, - "unit test fail"); - static_assert( - std::is_same>::value, - "unit test fail"); - static_assert( - std::is_same>>::value, - "unit test fail"); - - static_assert( - std::is_same>::value, - "unit test fail"); - static_assert( - std::is_same>::value, - "unit test fail"); - static_assert( - std::is_same, int>>::value, - "unit test fail"); - - static_assert( - std::is_same>::value, - "unit test fail"); - static_assert( - std::is_same>::value, - "unit test fail"); - static_assert( - std::is_same, const int&>>::value, - "unit test fail"); - } -} - -TEST_CASE("is_invocable"){ - SECTION("is_invocable_functions"){ - static_assert( - inv::is_invocable::value, - "unit test fail"); - static_assert( - inv::is_invocable::value, - "unit test fail"); - static_assert( - inv::is_invocable::value, - "unit test fail"); - } - SECTION("is_not_invocable_functions"){ - static_assert( - !inv::is_invocable::value, - "unit test fail"); - static_assert( - !inv::is_invocable::value, - "unit test fail"); - static_assert( - !inv::is_invocable::value, - "unit test fail"); - } - SECTION("is_invocable_members"){ - static_assert( - inv::is_invocable::value, - "unit test fail"); - static_assert( - inv::is_invocable::value, - "unit test fail"); - static_assert( - inv::is_invocable>::value, - "unit test fail"); - - static_assert( - inv::is_invocable::value, - "unit test fail"); - static_assert( - inv::is_invocable::value, - "unit test fail"); - static_assert( - inv::is_invocable>::value, - "unit test fail"); - - static_assert( - inv::is_invocable::value, - "unit test fail"); - static_assert( - inv::is_invocable::value, - "unit test fail"); - static_assert( - inv::is_invocable, int>::value, - "unit test fail"); - } - SECTION("is_not_invocable_members"){ - static_assert( - !inv::is_invocable::value, - "unit test fail"); - static_assert( - !inv::is_invocable::value, - "unit test fail"); - static_assert( - !inv::is_invocable*>::value, - "unit test fail"); - - static_assert( - !inv::is_invocable::value, - "unit test fail"); - static_assert( - !inv::is_invocable::value, - "unit test fail"); - static_assert( - !inv::is_invocable>::value, - "unit test fail"); - - static_assert( - !inv::is_invocable::value, - "unit test fail"); - static_assert( - !inv::is_invocable::value, - "unit test fail"); - static_assert( - !inv::is_invocable, int>::value, - "unit test fail"); - } - SECTION("is_invocable_objects"){ - static_assert( - inv::is_invocable::value, - "unit test fail"); - static_assert( - inv::is_invocable::value, - "unit test fail"); - static_assert( - inv::is_invocable>::value, - "unit test fail"); - - static_assert( - inv::is_invocable::value, - "unit test fail"); - static_assert( - inv::is_invocable::value, - "unit test fail"); - static_assert( - inv::is_invocable>::value, - "unit test fail"); - } - SECTION("is_not_invocable_objects"){ - static_assert( - !inv::is_invocable::value, - "unit test fail"); - static_assert( - !inv::is_invocable::value, - "unit test fail"); - static_assert( - !inv::is_invocable::value, - "unit test fail"); - - static_assert( - !inv::is_invocable::value, - "unit test fail"); - static_assert( - !inv::is_invocable::value, - "unit test fail"); - static_assert( - !inv::is_invocable>::value, - "unit test fail"); - } -} - -TEST_CASE("is_invocable_r"){ - SECTION("is_invocable_r_functions"){ - static_assert( - inv::is_invocable_r::value, - "unit test fail"); - static_assert( - inv::is_invocable_r::value, - "unit test fail"); - static_assert( - inv::is_invocable_r::value, - "unit test fail"); - static_assert( - inv::is_invocable_r::value, - "unit test fail"); - } - SECTION("is_not_invocable_r_functions"){ - static_assert( - !inv::is_invocable_r::value, - "unit test fail"); - static_assert( - !inv::is_invocable_r::value, - "unit test fail"); - static_assert( - !inv::is_invocable_r::value, - "unit test fail"); - - static_assert( - !inv::is_invocable_r::value, - "unit test fail"); - static_assert( - !inv::is_invocable_r::value, - "unit test fail"); - static_assert( - !inv::is_invocable_r::value, - "unit test fail"); - } - SECTION("is_invocable_r_members"){ - static_assert( - inv::is_invocable_r::value, - "unit test fail"); - static_assert( - inv::is_invocable_r::value, - "unit test fail"); - static_assert( - inv::is_invocable_r>::value, - "unit test fail"); - - static_assert( - inv::is_invocable_r::value, - "unit test fail"); - static_assert( - inv::is_invocable_r::value, - "unit test fail"); - static_assert( - inv::is_invocable_r>::value, - "unit test fail"); - static_assert( - inv::is_invocable_r>::value, - "unit test fail"); - - static_assert( - inv::is_invocable_r::value, - "unit test fail"); - static_assert( - inv::is_invocable_r::value, - "unit test fail"); - static_assert( - inv::is_invocable_r, int>::value, - "unit test fail"); - static_assert( - inv::is_invocable_r, int>::value, - "unit test fail"); - } - SECTION("is_not_invocable_r_members"){ - static_assert( - !inv::is_invocable_r::value, - "unit test fail"); - static_assert( - !inv::is_invocable_r::value, - "unit test fail"); - static_assert( - !inv::is_invocable_r>::value, - "unit test fail"); - - static_assert( - !inv::is_invocable_r::value, - "unit test fail"); - static_assert( - !inv::is_invocable_r::value, - "unit test fail"); - static_assert( - !inv::is_invocable_r>::value, - "unit test fail"); - - static_assert( - !inv::is_invocable_r::value, - "unit test fail"); - static_assert( - !inv::is_invocable_r::value, - "unit test fail"); - static_assert( - !inv::is_invocable_r, obj2_t>::value, - "unit test fail"); - } - SECTION("is_invocable_r_objects"){ - static_assert( - inv::is_invocable_r::value, - "unit test fail"); - static_assert( - inv::is_invocable_r::value, - "unit test fail"); - static_assert( - inv::is_invocable_r>::value, - "unit test fail"); - static_assert( - inv::is_invocable_r>::value, - "unit test fail"); - - static_assert( - inv::is_invocable_r::value, - "unit test fail"); - static_assert( - inv::is_invocable_r::value, - "unit test fail"); - static_assert( - inv::is_invocable_r>::value, - "unit test fail"); - static_assert( - inv::is_invocable_r>::value, - "unit test fail"); - } - SECTION("is_not_invocable_r_objects"){ - static_assert( - !inv::is_invocable_r::value, - "unit test fail"); - static_assert( - !inv::is_invocable_r::value, - "unit test fail"); - static_assert( - !inv::is_invocable_r, obj2_t>::value, - "unit test fail"); - static_assert( - !inv::is_invocable_r, obj2_t>::value, - "unit test fail"); - - static_assert( - !inv::is_invocable_r::value, - "unit test fail"); - static_assert( - !inv::is_invocable_r::value, - "unit test fail"); - static_assert( - !inv::is_invocable_r>::value, - "unit test fail"); - static_assert( - !inv::is_invocable_r>::value, - "unit test fail"); - } -} - -TEST_CASE("apply"){ - SECTION("apply_functions"){ - inv::apply(simple_static_function, std::make_tuple()); - REQUIRE(inv::apply(simple_static_function_r, std::make_tuple()) == 42); - REQUIRE(inv::apply(simple_static_function_r_with_arg, std::make_tuple(42)) == 42); - { - int v = 42; - REQUIRE(&inv::apply(simple_static_function_r_with_ref_arg, std::make_tuple(std::ref(v))) == &v); - } - } - SECTION("apply_members"){ - obj_t o; - - inv::apply(&obj_t::member, std::make_tuple(o)); - inv::apply(&obj_t::member, std::make_tuple(&o)); - inv::apply(&obj_t::member, std::make_tuple(std::ref(o))); - - REQUIRE(inv::apply(&obj_t::member_r, std::make_tuple(o)) == 42); - REQUIRE(inv::apply(&obj_t::member_r, std::make_tuple(&o)) == 42); - REQUIRE(inv::apply(&obj_t::member_r, std::make_tuple(std::ref(o))) == 42); - - REQUIRE(inv::apply(&obj_t::member_r_with_arg, std::make_tuple(o, 42)) == 42); - REQUIRE(inv::apply(&obj_t::member_r_with_arg, std::make_tuple(&o, 42)) == 42); - REQUIRE(inv::apply(&obj_t::member_r_with_arg, std::make_tuple(std::ref(o), 42)) == 42); - - { - int v = 42; - REQUIRE(&inv::apply(&obj_t::member_r_with_ref_arg, std::make_tuple(o, std::ref(v))) == &v); - REQUIRE(&inv::apply(&obj_t::member_r_with_ref_arg, std::make_tuple(&o, std::ref(v))) == &v); - REQUIRE(&inv::apply(&obj_t::member_r_with_ref_arg, std::make_tuple(std::ref(o), std::ref(v))) == &v); - } - } - SECTION("apply_member_objects"){ - obj_t o; - - REQUIRE(inv::apply(&obj_t::value, std::make_tuple(o)) == 42); - REQUIRE(inv::apply(&obj_t::value, std::make_tuple(&o)) == 42); - REQUIRE(inv::apply(&obj_t::value, std::make_tuple(std::ref(o))) == 42); - - REQUIRE(inv::apply(&obj_t::value_c, std::make_tuple(o)) == 42); - REQUIRE(inv::apply(&obj_t::value_c, std::make_tuple(&o)) == 42); - REQUIRE(inv::apply(&obj_t::value_c, std::make_tuple(std::ref(o))) == 42); - } -} From b8114145b9d8a620dbe8751d34e406dc22df76c8 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Sat, 28 Dec 2019 12:31:54 +0700 Subject: [PATCH 2/3] extract jobber thread ids --- headers/promise.hpp/jobber.hpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/headers/promise.hpp/jobber.hpp b/headers/promise.hpp/jobber.hpp index a398aca..615c00a 100644 --- a/headers/promise.hpp/jobber.hpp +++ b/headers/promise.hpp/jobber.hpp @@ -58,6 +58,10 @@ namespace jobber_hpp void resume() noexcept; bool is_paused() const noexcept; + std::size_t thread_count() const noexcept; + std::thread::id thread_id(std::size_t i) const; + std::vector thread_ids() const; + jobber_wait_status wait_all() const noexcept; active_wait_result_t active_wait_all() noexcept; active_wait_result_t active_wait_one() noexcept; @@ -189,6 +193,23 @@ namespace jobber_hpp return paused_; } + inline std::size_t jobber::thread_count() const noexcept { + return threads_.size(); + } + + inline std::thread::id jobber::thread_id(std::size_t i) const { + return threads_[i].get_id(); + } + + inline std::vector jobber::thread_ids() const { + std::vector ids; + ids.reserve(threads_.size()); + for ( const std::thread& t : threads_ ) { + ids.push_back(t.get_id()); + } + return ids; + } + inline jobber_wait_status jobber::wait_all() const noexcept { std::unique_lock lock(tasks_mutex_); cond_var_.wait(lock, [this](){ From 7fbac493ad24b99e06160ade1933296ee4b52046 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Sat, 28 Dec 2019 12:54:33 +0700 Subject: [PATCH 3/3] fix CI --- .appveyor.yml | 49 ++++- .travis.yml | 198 ++++++++++++------ scripts/build_all.bat | 6 +- scripts/build_debug.sh | 6 +- .../{build_debug.bat => build_debug_x64.bat} | 8 +- scripts/build_debug_x86.bat | 14 ++ scripts/build_release.sh | 6 +- ...uild_release.bat => build_release_x64.bat} | 8 +- scripts/build_release_x86.bat | 14 ++ scripts/upload_coverage.sh | 4 +- 10 files changed, 227 insertions(+), 86 deletions(-) rename scripts/{build_debug.bat => build_debug_x64.bat} (57%) create mode 100644 scripts/build_debug_x86.bat rename scripts/{build_release.bat => build_release_x64.bat} (56%) create mode 100644 scripts/build_release_x86.bat diff --git a/.appveyor.yml b/.appveyor.yml index 27089cb..b3272fe 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -1,12 +1,45 @@ -version: "{build}" -shallow_clone: true image: - - Visual Studio 2015 - Visual Studio 2017 - - Visual Studio 2019 Preview + - Visual Studio 2019 + platform: - - Win32 + - x86 - x64 -build_script: - - scripts\build_all.bat -test: off + +configuration: + - Debug + - Release + +for: + +- + matrix: + only: + - platform: x86 + configuration: Debug + build_script: + - scripts\build_debug_x86.bat + +- + matrix: + only: + - platform: x64 + configuration: Debug + build_script: + - scripts\build_debug_x64.bat + +- + matrix: + only: + - platform: x86 + configuration: Release + build_script: + - scripts\build_release_x86.bat + +- + matrix: + only: + - platform: x64 + configuration: Release + build_script: + - scripts\build_release_x64.bat diff --git a/.travis.yml b/.travis.yml index 5ea4d0f..37e0eac 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,81 +1,159 @@ language: cpp + matrix: include: + + # + # windows (MSVC 2017) + # + + - os: windows + stage: windows + name: debug, MSVC 2017, x86 + script: ./scripts/build_debug_x86.bat + + - os: windows + stage: windows + name: release, MSVC 2017, x86 + script: ./scripts/build_release_x86.bat + + - os: windows + stage: windows + name: debug, MSVC 2017, x64 + script: ./scripts/build_debug_x64.bat + + - os: windows + stage: windows + name: release, MSVC 2017, x64 + script: ./scripts/build_release_x64.bat + + # + # linux (g++-7) + # + - os: linux - dist: trusty - addons: { apt: { sources: ubuntu-toolchain-r-test, packages: ["xorg-dev", "g++-4.9"] } } - env: MATRIX_EVAL="CC=gcc-4.9 && CXX=g++-4.9" + dist: xenial + stage: linux + name: debug, g++-7 + addons: { apt: { sources: ["ubuntu-toolchain-r-test"], packages: ["g++-7"] } } + env: CC=gcc-7 CXX=g++-7 + script: ./scripts/build_debug.sh + - os: linux - dist: trusty - addons: { apt: { sources: ubuntu-toolchain-r-test, packages: ["xorg-dev", "g++-5"] } } - env: MATRIX_EVAL="CC=gcc-5 && CXX=g++-5" + dist: xenial + stage: linux + name: release, g++-7 + addons: { apt: { sources: ["ubuntu-toolchain-r-test"], packages: ["g++-7"] } } + env: CC=gcc-7 CXX=g++-7 + script: ./scripts/build_release.sh + + # + # linux (g++-8) + # + - os: linux - dist: trusty - addons: { apt: { sources: ubuntu-toolchain-r-test, packages: ["xorg-dev", "g++-6"] } } - env: MATRIX_EVAL="CC=gcc-6 && CXX=g++-6" + dist: xenial + stage: linux + name: debug, g++-8 + addons: { apt: { sources: ["ubuntu-toolchain-r-test"], packages: ["g++-8"] } } + env: CC=gcc-8 CXX=g++-8 + script: ./scripts/build_debug.sh + - os: linux - dist: trusty - addons: { apt: { sources: ubuntu-toolchain-r-test, packages: ["xorg-dev", "g++-7"] } } - env: MATRIX_EVAL="CC=gcc-7 && CXX=g++-7" + dist: xenial + stage: linux + name: release, g++-8 + addons: { apt: { sources: ["ubuntu-toolchain-r-test"], packages: ["g++-8"] } } + env: CC=gcc-8 CXX=g++-8 + script: ./scripts/build_release.sh + + # + # linux (clang++-5.0) + # + - os: linux - dist: trusty - addons: { apt: { sources: ubuntu-toolchain-r-test, packages: ["xorg-dev", "g++-8"] } } - env: MATRIX_EVAL="CC=gcc-8 && CXX=g++-8" + dist: xenial + stage: linux + name: debug, clang++-5.0 + addons: { apt: { sources: ["ubuntu-toolchain-r-test", "llvm-toolchain-xenial-5.0"], packages: ["g++-7", "clang-5.0"] } } + env: CC=clang-5.0 CXX=clang++-5.0 + script: ./scripts/build_debug.sh + - os: linux - dist: trusty - addons: { apt: { sources: ["ubuntu-toolchain-r-test", "llvm-toolchain-precise-3.8"], packages: ["xorg-dev", "clang-3.8", "g++-5"] } } - env: MATRIX_EVAL="CC=clang-3.8 && CXX=clang++-3.8" + dist: xenial + stage: linux + name: release, clang++-5.0 + addons: { apt: { sources: ["ubuntu-toolchain-r-test", "llvm-toolchain-xenial-5.0"], packages: ["g++-7", "clang-5.0"] } } + env: CC=clang-5.0 CXX=clang++-5.0 + script: ./scripts/build_release.sh + + # + # linux (clang++-6.0) + # + - os: linux - dist: trusty - addons: { apt: { sources: ["ubuntu-toolchain-r-test", "llvm-toolchain-precise-3.9"], packages: ["xorg-dev", "clang-3.9", "g++-5"] } } - env: MATRIX_EVAL="CC=clang-3.9 && CXX=clang++-3.9" + dist: xenial + stage: linux + name: debug, clang++-6.0 + addons: { apt: { sources: ["ubuntu-toolchain-r-test", "llvm-toolchain-xenial-6.0"], packages: ["g++-7", "clang-6.0"] } } + env: CC=clang-6.0 CXX=clang++-6.0 + script: ./scripts/build_debug.sh + - os: linux - dist: trusty - addons: { apt: { sources: ["ubuntu-toolchain-r-test", "llvm-toolchain-trusty-4.0"], packages: ["xorg-dev", "clang-4.0", "g++-5"] } } - env: MATRIX_EVAL="CC=clang-4.0 && CXX=clang++-4.0" - - os: linux - dist: trusty - addons: { apt: { sources: ["ubuntu-toolchain-r-test", "llvm-toolchain-trusty-5.0"], packages: ["xorg-dev", "clang-5.0", "g++-7"] } } - env: MATRIX_EVAL="CC=clang-5.0 && CXX=clang++-5.0" - - os: linux - dist: trusty - addons: { apt: { sources: ["ubuntu-toolchain-r-test", "llvm-toolchain-trusty-6.0"], packages: ["xorg-dev", "clang-6.0", "g++-7"] } } - env: MATRIX_EVAL="CC=clang-6.0 && CXX=clang++-6.0" - - os: osx - osx_image: xcode8.3 - compiler: clang - - os: osx - osx_image: xcode9 - compiler: clang - - os: osx - osx_image: xcode9.1 - compiler: clang - - os: osx - osx_image: xcode9.2 - compiler: clang - - os: osx - osx_image: xcode9.3 - compiler: clang - - os: osx - osx_image: xcode9.4 - compiler: clang + dist: xenial + stage: linux + name: release, clang++-6.0 + addons: { apt: { sources: ["ubuntu-toolchain-r-test", "llvm-toolchain-xenial-6.0"], packages: ["g++-7", "clang-6.0"] } } + env: CC=clang-6.0 CXX=clang++-6.0 + script: ./scripts/build_release.sh + + # + # macosx (xcode10) + # + - os: osx osx_image: xcode10 - compiler: clang + stage: macosx + name: debug, xcode10 + script: ./scripts/build_debug.sh + + - os: osx + osx_image: xcode10 + stage: macosx + name: release, xcode10 + script: ./scripts/build_release.sh + + # + # macosx (xcode11) + # + + - os: osx + osx_image: xcode11 + stage: macosx + name: debug, xcode11 + script: ./scripts/build_debug.sh + + - os: osx + osx_image: xcode11 + stage: macosx + name: release, xcode11 + script: ./scripts/build_release.sh + + # + # coverage + # + + - os: osx + osx_image: xcode10 + stage: coverage + name: coverage, xcode10 addons: { homebrew: { packages: ["lcov"] } } - after_success: ./scripts/upload_coverage.sh + script: ./scripts/upload_coverage.sh + before_install: - - eval "${MATRIX_EVAL}" - - if [ "$TRAVIS_OS_NAME" == 'osx' ]; then - brew update; - brew upgrade cmake; - brew install git-lfs; - fi - if [ "$TRAVIS_OS_NAME" == 'linux' ]; then mkdir $HOME/cmake; export PATH="$HOME/cmake/bin:$PATH"; travis_retry wget -q https://cmake.org/files/v3.11/cmake-3.11.4-Linux-x86_64.sh; sh cmake-3.11.4-Linux-x86_64.sh --prefix=$HOME/cmake --exclude-subdir --skip-license; fi -script: - - ./scripts/build_all.sh diff --git a/scripts/build_all.bat b/scripts/build_all.bat index 4d063dc..9e778dc 100644 --- a/scripts/build_all.bat +++ b/scripts/build_all.bat @@ -1,7 +1,9 @@ @echo off set SCRIPT_DIR=%~dp0% -call %SCRIPT_DIR%\build_debug.bat || goto :error -call %SCRIPT_DIR%\build_release.bat || goto :error +call %SCRIPT_DIR%\build_debug_x86.bat || goto :error +call %SCRIPT_DIR%\build_debug_x64.bat || goto :error +call %SCRIPT_DIR%\build_release_x86.bat || goto :error +call %SCRIPT_DIR%\build_release_x64.bat || goto :error goto :EOF diff --git a/scripts/build_debug.sh b/scripts/build_debug.sh index 89f4c93..97018eb 100755 --- a/scripts/build_debug.sh +++ b/scripts/build_debug.sh @@ -1,9 +1,9 @@ #!/bin/bash set -e BUILD_DIR=`dirname "$BASH_SOURCE"`/../build -mkdir -p $BUILD_DIR/debug -cd $BUILD_DIR/debug +mkdir -p $BUILD_DIR/Debug +cd $BUILD_DIR/Debug cmake -DCMAKE_BUILD_TYPE=Debug ../.. -cmake --build . -- -j8 +cmake --build . ctest --verbose cd ../.. diff --git a/scripts/build_debug.bat b/scripts/build_debug_x64.bat similarity index 57% rename from scripts/build_debug.bat rename to scripts/build_debug_x64.bat index 01f8572..675bd2a 100644 --- a/scripts/build_debug.bat +++ b/scripts/build_debug_x64.bat @@ -1,11 +1,11 @@ @echo off set BUILD_DIR=%~dp0%\..\build -mkdir %BUILD_DIR%\debug || goto :error -cd %BUILD_DIR%\debug || goto :error -cmake ../.. || goto :error +mkdir %BUILD_DIR%\Debug\x64 || goto :error +cd %BUILD_DIR%\Debug\x64 || goto :error +cmake ..\..\.. -A x64 || goto :error cmake --build . --config Debug || goto :error ctest --verbose || goto :error -cd ..\.. || goto :error +cd ..\..\.. || goto :error goto :EOF diff --git a/scripts/build_debug_x86.bat b/scripts/build_debug_x86.bat new file mode 100644 index 0000000..b6dcd6d --- /dev/null +++ b/scripts/build_debug_x86.bat @@ -0,0 +1,14 @@ +@echo off +set BUILD_DIR=%~dp0%\..\build +mkdir %BUILD_DIR%\Debug\x86 || goto :error +cd %BUILD_DIR%\Debug\x86 || goto :error +cmake ..\..\.. -A Win32 || goto :error +cmake --build . --config Debug || goto :error +ctest --verbose || goto :error +cd ..\..\.. || goto :error + +goto :EOF + +:error +echo Failed with error #%errorlevel%. +exit /b %errorlevel% diff --git a/scripts/build_release.sh b/scripts/build_release.sh index 9ab7e23..3a2c5c1 100755 --- a/scripts/build_release.sh +++ b/scripts/build_release.sh @@ -1,9 +1,9 @@ #!/bin/bash set -e BUILD_DIR=`dirname "$BASH_SOURCE"`/../build -mkdir -p $BUILD_DIR/release -cd $BUILD_DIR/release +mkdir -p $BUILD_DIR/Release +cd $BUILD_DIR/Release cmake -DCMAKE_BUILD_TYPE=Release ../.. -cmake --build . -- -j8 +cmake --build . ctest --verbose cd ../.. diff --git a/scripts/build_release.bat b/scripts/build_release_x64.bat similarity index 56% rename from scripts/build_release.bat rename to scripts/build_release_x64.bat index b6bf362..064e867 100644 --- a/scripts/build_release.bat +++ b/scripts/build_release_x64.bat @@ -1,11 +1,11 @@ @echo off set BUILD_DIR=%~dp0%\..\build -mkdir %BUILD_DIR%\release || goto :error -cd %BUILD_DIR%\release || goto :error -cmake ../.. || goto :error +mkdir %BUILD_DIR%\Release\x64 || goto :error +cd %BUILD_DIR%\Release\x64 || goto :error +cmake ..\..\.. -A x64 || goto :error cmake --build . --config Release || goto :error ctest --verbose || goto :error -cd ..\.. || goto :error +cd ..\..\.. || goto :error goto :EOF diff --git a/scripts/build_release_x86.bat b/scripts/build_release_x86.bat new file mode 100644 index 0000000..09aa042 --- /dev/null +++ b/scripts/build_release_x86.bat @@ -0,0 +1,14 @@ +@echo off +set BUILD_DIR=%~dp0%\..\build +mkdir %BUILD_DIR%\Release\x86 || goto :error +cd %BUILD_DIR%\Release\x86 || goto :error +cmake ..\..\.. -A Win32 || goto :error +cmake --build . --config Release || goto :error +ctest --verbose || goto :error +cd ..\..\.. || goto :error + +goto :EOF + +:error +echo Failed with error #%errorlevel%. +exit /b %errorlevel% diff --git a/scripts/upload_coverage.sh b/scripts/upload_coverage.sh index b1eef21..b36265d 100755 --- a/scripts/upload_coverage.sh +++ b/scripts/upload_coverage.sh @@ -5,13 +5,13 @@ BUILD_DIR=`dirname "$BASH_SOURCE"`/../build mkdir -p $BUILD_DIR/coverage cd $BUILD_DIR/coverage cmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_WITH_COVERAGE=ON ../.. -cmake --build . -- -j8 +cmake --build . lcov -d . -z ctest --verbose lcov -d . -c -o "coverage.info" -lcov -r "coverage.info" "*/usr/*" "*/catch.hpp" "*/catch_main.cpp" "*_tests.cpp" -o "coverage.info" +lcov -r "coverage.info" "*/usr/*" "*/catch.hpp" "*/catch_main.cpp" "*_tests.cpp" "*_examples.cpp" -o "coverage.info" lcov -l "coverage.info" bash <(curl -s https://codecov.io/bash) || echo "Codecov did not collect coverage reports"