phoenix/test/statement/exceptions.cpp
2015-03-28 22:55:15 +00:00

195 lines
4.6 KiB
C++

/*=============================================================================
Copyright (c) 2005-2007 Dan Marsden
Copyright (c) 2005-2007 Joel de Guzman
Copyright (c) 2015 John Fletcher
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)
==============================================================================*/
#include <stdexcept>
#include <string>
#include <boost/phoenix/core.hpp>
#include <boost/phoenix/operator.hpp>
#include <boost/phoenix/statement.hpp>
#include <boost/phoenix/scope/local_variable.hpp>
#include <boost/phoenix/bind/bind_member_function.hpp>
#include <boost/detail/lightweight_test.hpp>
struct base_exception : std::exception
{
explicit
base_exception(char const *msg)
: _sliced(true), _what(msg)
{}
base_exception(base_exception const &other)
: _sliced(true), _what(other._what)
{
}
char const *what() const BOOST_NOEXCEPT_OR_NOTHROW
{
if (_sliced) { return "sliced ..."; }
return _what;
}
bool _sliced;
char const *_what;
};
struct extended_exception : base_exception
{
explicit
extended_exception(char const *msg)
: base_exception(msg)
{
// mark as not sliced
_sliced = false;
}
extended_exception(extended_exception const &other)
: base_exception(other)
{
// mark as not sliced
_sliced = false;
}
};
int main()
{
using boost::phoenix::throw_;
using boost::phoenix::try_;
using boost::phoenix::ref;
using boost::phoenix::local_names::_e;
using boost::phoenix::bind;
using std::exception;
using std::string;
using std::runtime_error;
namespace phx = boost::phoenix;
{
try
{
throw_(runtime_error("error"))();
BOOST_ERROR("exception should have been thrown");
}
catch(runtime_error& err)
{
BOOST_TEST(err.what() == string("error"));
}
}
{
try
{
try
{
throw runtime_error("error");
}
catch(exception&)
{
throw_()();
BOOST_ERROR("exception should have been rethrown");
}
}
catch(exception& err)
{
BOOST_TEST(err.what() == string("error"));
}
}
{
bool caught_exception = false;
try_
[ throw_(runtime_error("error")) ]
.catch_<exception>(_e) // captured but unused
[
ref(caught_exception) = true
]();
BOOST_TEST(caught_exception);
}
{
bool caught_exception = false;
string what;
try_
[ throw_(runtime_error("error")) ]
.catch_<exception>(_e)
[
ref(caught_exception) = true
// ambiguous with std::ref
, phx::ref(what) = phx::bind(&exception::what, _e)
]();
BOOST_TEST(caught_exception);
BOOST_TEST(what == string("error"));
}
{
bool caught_exception = false;
string what;
try_
[ throw_(extended_exception("error")) ]
.catch_<base_exception>(_e) // A thrown object should not be copied due to slicing.
[
ref(caught_exception) = true
// ambiguous with std::ref
, phx::ref(what) = phx::bind(&exception::what, _e)
]();
BOOST_TEST(caught_exception);
BOOST_TEST(what == string("error"));
}
{
bool caught_exception = false;
try_
[ throw_(runtime_error("error")) ]
.catch_all
[ ref(caught_exception) = true ]();
BOOST_TEST(caught_exception);
}
{
bool caught_correct_exception = false;
string what;
try_
[ throw_(runtime_error("error")) ]
.catch_<string>()
[ ref(caught_correct_exception) = false ]
.catch_<exception>(_e)
[
ref(caught_correct_exception) = true
// ambiguous with std::ref
, phx::ref(what) = phx::bind(&exception::what, _e)
]();
BOOST_TEST(caught_correct_exception);
BOOST_TEST(what == string("error"));
}
{
bool caught_correct_exception = false;
try_
[ throw_(runtime_error("error")) ]
.catch_<string>()
[ ref(caught_correct_exception) = false ]
.catch_all
[ ref(caught_correct_exception) = true]();
BOOST_TEST(caught_correct_exception);
}
return boost::report_errors();
}