Last active
June 18, 2022 05:31
-
-
Save karagog/ab41468ea82a8fb54cde to your computer and use it in GitHub Desktop.
Try-Catch-Finally in C++
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <exception> | |
#include <string> | |
#include "trycatchfinally.h" | |
using namespace std; | |
int main() | |
{ | |
// No exception | |
TryFinally( | |
[]{ cout<<"Try Body"<<endl; }, | |
[](exception){ cout<<"Catch Body"<<endl; }, | |
[]{ cout<<"Finally Body"<<endl; } | |
); | |
// Exception thrown | |
TryFinally( | |
[]{ cout<<"Try Body"<<endl; throw exception(); }, | |
[](exception){ cout<<"Catch Body"<<endl; }, | |
[]{ cout<<"Finally Body"<<endl; } | |
); | |
// You can even change values in this scope (notice the [&]?) | |
string what; | |
TryFinally( | |
[]{ throw exception(); }, | |
[&](const exception &ex){ what = ex.what(); }, | |
[]{} | |
); | |
cout<<what<<endl; | |
// What about custom exception types? | |
class test_exception_t : public std::exception{ public: | |
virtual const char *what() const noexcept{ return "My Test Exception"; } | |
}; | |
TryFinally( | |
[]{ throw test_exception_t(); }, | |
[](const exception &ex){ cout<<ex.what()<<endl; }, | |
[]{} | |
); | |
// Can you tell the difference between two types of exceptions? | |
class second_exception_t : public std::exception{ public: | |
virtual const char *what() const noexcept{ return "My Second Test Exception"; } | |
string name; | |
}; | |
TryFinally( | |
[]{ throw second_exception_t(); }, | |
[](const exception &ex){ | |
if(NULL == dynamic_cast<test_exception_t const *>(&ex)) | |
cout<<"This is not the first kind of exception"<<endl; | |
if(NULL != dynamic_cast<second_exception_t const *>(&ex)) | |
cout<<"This is the second kind of exception"<<endl; | |
}, | |
[]{} | |
); | |
// What about exception types that aren't derived from std::exception? | |
TryFinally<const char *>( | |
[]{ throw "This is not even an exception!"; }, | |
[](const char *ex){ cout<<ex<<endl; }, | |
[]{} | |
); | |
// If you fail to catch the exception, the finally should still execute | |
try{ | |
TryFinally( | |
[]{ throw "This is not even an exception!"; }, | |
[](exception){ cout<<"This should not execute because we didn't catch the right type"<<endl; }, | |
[]{ cout<<"Finally body still executes"<<endl; } | |
); | |
} catch(...){ | |
cout<<"Exception escaped"<<endl; | |
} | |
// Let's do something more complex. I will modify and rethrow the exception | |
try{ | |
TryFinally( | |
[]{ throw second_exception_t(); }, | |
[](exception &ex){ | |
// Let's give the exception a name and rethrow it | |
second_exception_t *s = dynamic_cast<second_exception_t *>(&ex); | |
s->name = "George"; | |
// I don't even need to tell it what to throw | |
throw; | |
}, | |
[]{ cout<<"Finally Body"<<endl; } | |
); | |
} | |
catch(const second_exception_t &ex){ | |
cout<<"Exception named "<<ex.name<<endl; | |
} | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*Copyright 2014 George Karagoulis | |
Licensed under the Apache License, Version 2.0 (the "License"); | |
you may not use this file except in compliance with the License. | |
You may obtain a copy of the License at | |
http://www.apache.org/licenses/LICENSE-2.0 | |
Unless required by applicable law or agreed to in writing, software | |
distributed under the License is distributed on an "AS IS" BASIS, | |
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
See the License for the specific language governing permissions and | |
limitations under the License.*/ | |
/** A nifty try catch finally construction made possible by c++11's new lambda functions. | |
* It behaves just like you would want a try-catch-finally to behave, with a few minor | |
* querks. Firstly you can only catch one type of exception, the base type | |
* of all your exceptions, and if you want to know its type you dynamic cast its pointer. | |
* | |
* The default usage, which catches std::exception and has no code looks like this: | |
* | |
* TryFinally( | |
* []{}, // Try body | |
* [](const std::exception &){}, // Catch body | |
* []{}); // Finally body | |
* | |
* Note that the catch function should handle with a const reference, because it | |
* allows you to check which type the exception instance is. | |
* | |
* If you want to catch a custom exception type other than std::exception, call it "MyException", | |
* it looks like this: | |
* | |
* TryFinally<MyException>( | |
* []{}, // Try body | |
* [](const MyException &){}, // Catch body | |
* []{}); // Finally body | |
* | |
* \tparam EXCEPTION The type of exception which will be caught. If an exception is thrown that | |
* doesn't derive from this base type, the finally body will be executed but not the catch. | |
* \param _try The try body. This is executed first. Exceptions thrown here will be handled by the catch body. | |
* \param _catch The catch body. This is only executed if an exception was thrown inside the try block. | |
* It is required to take the handled exception class as an argument. | |
* \param _finally The finally body. This is executed regardless of whether an exception was thrown, | |
* either from the try body or the catch body. | |
*/ | |
template<class EXCEPTION = std::exception, class TRY_BLOCK, class CATCH_BLOCK, class FINALLY_BLOCK> | |
inline void TryFinally(TRY_BLOCK _try, CATCH_BLOCK _catch, FINALLY_BLOCK _finally) | |
{ | |
try | |
{ | |
_try(); | |
} | |
catch(EXCEPTION &e) | |
{ | |
try | |
{ | |
_catch(e); | |
} | |
catch(...) | |
{ | |
_finally(); | |
throw; | |
} | |
} | |
catch(...) | |
{ | |
_finally(); | |
throw; | |
} | |
_finally(); | |
} |
Note that you have to build this with the compiler flag: --std=c++0x
I just built it with g++ 4.8.1
Very good, I'll try to use
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I have been studying the new c++ standard (c++11) and I was playing around with lambda functions today, and I came up with this implementation for try-catch-finally. Technically speaking, this was possible with the c++03 standard, but it would have been MUCH clunkier. The new lambda functions make this look actually quite sexy.