CodePorting.Translator Cs2Cpp
CodePorting.Translator.Cs2Cpp.Framework
do_try_finally.h
1
3#pragma once
4
5#include <exception>
6#include <functional>
7#include <system/details/value_init.h>
8#include <system/details/is_lambda.h>
9#include "defines.h"
10
11// https://stackoverflow.com/a/53365539
12// We haven't checked which optinal to include yet
13#ifndef INCLUDE_STD_OPTIONAL_EXPERIMENTAL
14
15// Check current standard
16
17// C++17
18# if CODEPORTING_CPP_STANDARD >= 17
19
20// Check for feature test macro for <optinal>
21# if defined(__cpp_lib_optional)
22# define INCLUDE_STD_OPTIONAL_EXPERIMENTAL 0
23
24// Check for feature test macro for <experimental/optional>
25# elif defined(__cpp_lib_experimental_optional)
26# define INCLUDE_STD_OPTIONAL_EXPERIMENTAL 1
27
28// We can't check if headers exist...
29// Let's assume experimental to be safe
30# elif !defined(__has_include)
31# define INCLUDE_STD_OPTIONAL_EXPERIMENTAL 1
32
33// Check if the header "<optional>" exists
34# elif __has_include(<optional>)
35
36// If we're compiling on Visual Studio and are not compiling with C++17, we need to use experimental
37# ifdef _MSC_VER
38
39// Check and include header that defines "_HAS_CXX17"
40# if __has_include(<yvals_core.h>)
41# include <yvals_core.h>
42
43// Check for enabled C++17 support
44# if defined(_HAS_CXX17) && _HAS_CXX17
45// We're using C++17, so let's use the normal version
46# define INCLUDE_STD_OPTIONAL_EXPERIMENTAL 0
47# elif __has_include(<experimental/optional>)
48# define INCLUDE_STD_OPTIONAL_EXPERIMENTAL 1
49# endif
50# endif
51
52// If the marco isn't defined yet, that means any of the other VS specific checks failed, so we need to use custom implementation
53# ifndef INCLUDE_STD_OPTIONAL_EXPERIMENTAL
54# define INCLUDE_STD_OPTIONAL_EXPERIMENTAL 2
55# endif
56
57// Not on Visual Studio. Let's use the normal version
58# else // #ifdef _MSC_VER
59# define INCLUDE_STD_OPTIONAL_EXPERIMENTAL 0
60# endif
61
62// Check if the header "<optional>" exists
63# elif __has_include(<experimental/optional>)
64# define INCLUDE_STD_OPTIONAL_EXPERIMENTAL 1
65
66// Fallback to custom implementation
67# else
68# define INCLUDE_STD_OPTIONAL_EXPERIMENTAL 2
69# endif
70
71// C++14
72# elif CODEPORTING_CPP_STANDARD >= 14
73
74// Check for feature test macro for <experimental/optional>
75# if defined(__cpp_lib_experimental_optional)
76# define INCLUDE_STD_OPTIONAL_EXPERIMENTAL 1
77# elif !defined(__has_include)
78# define INCLUDE_STD_OPTIONAL_EXPERIMENTAL 1
79
80// Check if the header "<experimental/optional>" exists
81# elif __has_include(<experimental/optional>)
82# define INCLUDE_STD_OPTIONAL_EXPERIMENTAL 1
83
84// Fallback to custom implementation
85# else
86# define INCLUDE_STD_OPTIONAL_EXPERIMENTAL 2
87# endif
88
89// Something else
90# else
91
92// Fallback to custom implementation
93# define INCLUDE_STD_OPTIONAL_EXPERIMENTAL 2
94
95# endif
96
97// We previously determined that we need the experimental version
98# if INCLUDE_STD_OPTIONAL_EXPERIMENTAL == 1
99// Include it
100# include <experimental/optional>
101
102// We need the alias from std::experimental::filesystem to std::filesystem
103namespace std {
104 template<typename T>
105 using optional = experimental::optional<T>;
106
107 constexpr auto nullopt = std::experimental::nullopt;
108}
109
110// It is MSVC with /std:c++14 flag, let's use custom implementation
111# elif INCLUDE_STD_OPTIONAL_EXPERIMENTAL == 2
112// Include it
113# include "details/optional.h"
114
115// We need the alias from std::experimental::optional to std::optional
116namespace std {
117 template<typename T>
118 using optional = experimental::optional<T>;
119
120 constexpr auto nullopt = std::experimental::nullopt;
121}
122
123// We have a decent compiler and can use the normal version
124# else
125// Include it
126# include <optional>
127# endif
128
129#endif // #ifndef INCLUDE_STD_OPTIONAL_EXPERIMENTAL
130
131
132namespace System
133{
134namespace Details
135{
136
139template <typename F>
140class FinallyGuard
141{
142public:
149 FinallyGuard(std::exception_ptr& exception, F&& finallyBlock)
150 : mException(exception), mFinallyBlock(std::move(finallyBlock))
151 {}
152
154 ~FinallyGuard()
155 {
156 try
157 {
158 mFinallyBlock();
159 }
160 catch (...)
161 {
162 mException = std::current_exception();
163 }
164 }
165private:
169 std::exception_ptr& mException;
170
173 F mFinallyBlock;
174};
175
182template<typename F>
183FinallyGuard<F> MakeFinallyGuard(std::exception_ptr& exception, F&& f)
184{
185 return FinallyGuard<F>(exception, std::move(f));
186}
187
197template <typename T, typename F>
198void DoTryFinallyImpl(T&& tryBlock, F&& finallyBlock)
199{
200 std::exception_ptr exception;
201 {
202 auto finally_guard = MakeFinallyGuard(exception, std::move(finallyBlock));
203
204 try
205 {
206 tryBlock();
207 }
208 catch (...)
209 {
210 exception = std::current_exception();
211 }
212 }
213
214 if (exception)
215 {
216 std::rethrow_exception(exception);
217 }
218}
219
220
221} // namespace Details
222
223// lambda - [](){}
236template<typename T, typename F>
237std::enable_if_t<Details::is_lambda_void_void<T>::value>
238DoTryFinally(T&& tryBlock, F&& finallyBlock)
239{
240 Details::DoTryFinallyImpl(tryBlock, finallyBlock);
241}
242
243// lambda - [](bool&){}
258template<typename T, typename F>
259std::enable_if_t<Details::is_lambda_void_boolref<T>::value, bool>
260DoTryFinally(T&& tryBlock, F&& finallyBlock)
261{
262 bool isReturned = true;
263 Details::DoTryFinallyImpl([&]() { tryBlock(isReturned); }, finallyBlock);
264 return isReturned;
265}
266
267// lambda - [](bool&) -> type {}
282template<typename T, typename F>
283std::enable_if_t<Details::is_lambda_nonovoid_boolref<T>::value, std::optional<Details::ResultOf<T, bool&>>>
284DoTryFinally(T&& tryBlock, F&& finallyBlock)
285{
286 using ReturnValueType = Details::ResultOf<T, bool&>;
287 ReturnValueType returnValue;
288
289 bool isReturned = true;
290
291 Details::DoTryFinallyImpl([&]() { returnValue = tryBlock(isReturned); }, finallyBlock);
292
293 return isReturned ? std::optional<ReturnValueType>(returnValue) : std::nullopt;
294}
295
296} // namespace System
Definition: db_command.h:9
std::enable_if_t< Details::is_lambda_void_void< T >::value > DoTryFinally(T &&tryBlock, F &&finallyBlock)
The sigle function that emulates behavior of C#'s try[-catch]-finally statement. During translation o...
Definition: do_try_finally.h:238