/* * Created by Joachim on 16/04/2019. * Adapted from donated nonius code. * * Distributed under the Boost Software License, Version 1.0. (See accompanying * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ // Invoke with a special case for void #ifndef TWOBLUECUBES_CATCH_DETAIL_COMPLETE_INVOKE_HPP_INCLUDED #define TWOBLUECUBES_CATCH_DETAIL_COMPLETE_INVOKE_HPP_INCLUDED #include "../../catch_enforce.h" #include <type_traits> #include <utility> namespace Catch { namespace Benchmark { namespace Detail { template <typename T> struct CompleteType { using type = T; }; template <> struct CompleteType<void> { struct type {}; }; template <typename T> using CompleteType_t = typename CompleteType<T>::type; template <typename Result> struct CompleteInvoker { template <typename Fun, typename... Args> static Result invoke(Fun&& fun, Args&&... args) { return std::forward<Fun>(fun)(std::forward<Args>(args)...); } }; template <> struct CompleteInvoker<void> { template <typename Fun, typename... Args> static CompleteType_t<void> invoke(Fun&& fun, Args&&... args) { std::forward<Fun>(fun)(std::forward<Args>(args)...); return {}; } }; template <typename Sig> using ResultOf_t = typename std::result_of<Sig>::type; // invoke and not return void :( template <typename Fun, typename... Args> CompleteType_t<ResultOf_t<Fun(Args...)>> complete_invoke(Fun&& fun, Args&&... args) { return CompleteInvoker<ResultOf_t<Fun(Args...)>>::invoke(std::forward<Fun>(fun), std::forward<Args>(args)...); } const std::string benchmarkErrorMsg = "a benchmark failed to run successfully"; } // namespace Detail template <typename Fun> Detail::CompleteType_t<Detail::ResultOf_t<Fun()>> user_code(Fun&& fun) { CATCH_TRY{ return Detail::complete_invoke(std::forward<Fun>(fun)); } CATCH_CATCH_ALL{ getResultCapture().benchmarkFailed(translateActiveException()); CATCH_RUNTIME_ERROR(Detail::benchmarkErrorMsg); } } } // namespace Benchmark } // namespace Catch #endif // TWOBLUECUBES_CATCH_DETAIL_COMPLETE_INVOKE_HPP_INCLUDED