On 17/11/2013 19:32, Alf P. Steinbach wrote:
On 17.11.2013 20:19, Stefan Ram wrote:
Today, I wanted to show RAII, like this:
#include <iostream>
#include <ostream>
#include <stdexcept>
struct K
{ K (){ ::std::cerr << "K" << ::std::endl; }
~K(){ ::std::cerr << "~K" << ::std::endl; }};
struct R
{ K * k; R() : k{ new K{} }{}
~R() { ::std::cerr << "~R" << ::std::endl; delete k; }};
int main(){ R r{}; throw ::std::runtime_error( "error" ); }
The output was:
K
terminate called after throwing an instance of 'std::runtime_error'
what(): error
This application has requested the Runtime to terminate it in an
unusual way.
Please contact the application's support team for more information.
--------------------------------
Process exited with return value 3
This is the usual process exit code from `abort`.
No ~K nor ~R in sight! Why?
It's unspecified whether stack unwinding happens when there is no
handler for an exception.
In this case, with this compiler, it didn't happen.
For my own little hobby programming I therefore (among many other
semi-good reasons) use a write-it-once-and-be-done-with-it `main`
function that catches any standard exception, as follows:
[code file="cppx/process/invoke_main.hpp"]
#pragma once
// Copyright (c) 2013 Alf P. Steinbach.
#include <rfc/cppx/Type_.h> // cppx::Type_, cppx::Type
#include <rfc/cppx/process/Exit_code.h> //
cppx::process::Exit_code::Enum
#include <functional> // std::function
#include <iostream> // std::clog
#include <stdexcept> // std::exception
#include <system_error> // std::system_error
namespace cppx{ namespace process{
using std::exception;
using std::function;
typedef Type_T_<void()>::T Main_function;
typedef function<Main_function> Main_functor;
typedef cppx::Type_T_<bool( exception const& )>::T Logger_function;
typedef function<Logger_function> Logger_functor;
inline bool stderr_logger( exception const& x )
{
using namespace std;
cerr << "!" << x.what();
if( auto p_syserr = dynamic_cast<system_error const*>( &x ) )
{
cerr << " (error code 0x" << uppercase << hex <<
p_syserr->code().value() << ")";
}
cerr << endl;
return !!clog;
}
inline int invoke_main(
Main_functor const& cpp_main,
Logger_functor const& log = stderr_logger
)
{
try
{
cpp_main();
return Exit_code::success;
}
catch( exception const& x )
{
log( x );
return Exit_code::failure;
}
catch( ... )
{
throw; // Uh oh.
}
}
} } // namespace cppx::process
[/code]
which you can use like this (also this provided in an include file, but
it's questionable whether that can be called a "header"):
[code file="cppx/default_main.impl.hpp"]
// Implementation file.
#include <rfc/cppx/process/invoke_main.hpp>
extern void cpp_main();
auto main() -> int { return cppx::process::invoke_main( &cpp_main ); }
[/code]
whence we get down to the nitty-gritty, namely what you then write in
each using program, like this:
void cpp_main()
{
// blah blah, my "main program" code, may throw
}
#include <rfc/cppx/default_main.impl.hpp>
Of course the include directive can be anywhere, and alternatively it
can be replaced with linking, or even (gasp!) writing the one-liner
`main` -- shown earlier above -- oneself...
Cheers & hth.,
- Alf
PS: There has been an article series about using a standard
write-it-once-and-be-done-with-it `main` in the ACCU Overload Journal. I
haven't read it though. Skimming lightly through one of the articles I
think I saw some not very general interest code there, but it may still
be worth checking out.
incredibly complex.