1 /* 2 * Created by Joachim on 16/04/2019. 3 * Adapted from donated nonius code. 4 * 5 * Distributed under the Boost Software License, Version 1.0. (See accompanying 6 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 */ 8 9 // Invoke with a special case for void 10 11 #ifndef TWOBLUECUBES_CATCH_DETAIL_COMPLETE_INVOKE_HPP_INCLUDED 12 #define TWOBLUECUBES_CATCH_DETAIL_COMPLETE_INVOKE_HPP_INCLUDED 13 14 #include "../../catch_enforce.h" 15 16 #include <type_traits> 17 #include <utility> 18 19 namespace Catch { 20 namespace Benchmark { 21 namespace Detail { 22 template <typename T> 23 struct CompleteType { using type = T; }; 24 template <> 25 struct CompleteType<void> { struct type {}; }; 26 27 template <typename T> 28 using CompleteType_t = typename CompleteType<T>::type; 29 30 template <typename Result> 31 struct CompleteInvoker { 32 template <typename Fun, typename... Args> invokeCatch::Benchmark::Detail::CompleteInvoker33 static Result invoke(Fun&& fun, Args&&... args) { 34 return std::forward<Fun>(fun)(std::forward<Args>(args)...); 35 } 36 }; 37 template <> 38 struct CompleteInvoker<void> { 39 template <typename Fun, typename... Args> invokeCatch::Benchmark::Detail::CompleteInvoker40 static CompleteType_t<void> invoke(Fun&& fun, Args&&... args) { 41 std::forward<Fun>(fun)(std::forward<Args>(args)...); 42 return {}; 43 } 44 }; 45 template <typename Sig> 46 using ResultOf_t = typename std::result_of<Sig>::type; 47 48 // invoke and not return void :( 49 template <typename Fun, typename... Args> complete_invoke(Fun && fun,Args &&...args)50 CompleteType_t<ResultOf_t<Fun(Args...)>> complete_invoke(Fun&& fun, Args&&... args) { 51 return CompleteInvoker<ResultOf_t<Fun(Args...)>>::invoke(std::forward<Fun>(fun), std::forward<Args>(args)...); 52 } 53 54 const std::string benchmarkErrorMsg = "a benchmark failed to run successfully"; 55 } // namespace Detail 56 57 template <typename Fun> user_code(Fun && fun)58 Detail::CompleteType_t<Detail::ResultOf_t<Fun()>> user_code(Fun&& fun) { 59 CATCH_TRY{ 60 return Detail::complete_invoke(std::forward<Fun>(fun)); 61 } CATCH_CATCH_ALL{ 62 getResultCapture().benchmarkFailed(translateActiveException()); 63 CATCH_RUNTIME_ERROR(Detail::benchmarkErrorMsg); 64 } 65 } 66 } // namespace Benchmark 67 } // namespace Catch 68 69 #endif // TWOBLUECUBES_CATCH_DETAIL_COMPLETE_INVOKE_HPP_INCLUDED 70