Enable usage of gsl::narrow with exceptions disabled

This solution uses the approach of boost::asio to enabling usage of the
library in environments where exception usage is either prohibited
or not feasible (due to code size constraints). A function template
gsl::throw_exception has been added, which in a normal environment just
throws the exception. However, when GSL_TERMINATE_ON_CONTRACT_VIOLATION
is defined the function is only declared by gsl and the definition of
this function template must be supplied by the library's user.

Closes: #468

Signed-off-by: Damian Jarek <damian.jarek93@gmail.com>
This commit is contained in:
Damian Jarek 2017-03-28 23:53:49 +02:00
parent 1f87ef73f1
commit fbfdacb45f
No known key found for this signature in database
GPG Key ID: 5E9BCA132716182B
2 changed files with 41 additions and 5 deletions

View File

@ -72,19 +72,55 @@ struct fail_fast : public std::logic_error
{ {
explicit fail_fast(char const* const message) : std::logic_error(message) {} explicit fail_fast(char const* const message) : std::logic_error(message) {}
}; };
} namespace details
{
template <typename Exception>
[[noreturn]] void throw_exception(Exception&& exception);
} //namespace details
} //namespace gsl
#if defined(GSL_THROW_ON_CONTRACT_VIOLATION) #if defined(GSL_THROW_ON_CONTRACT_VIOLATION)
namespace gsl
{
namespace details
{
template <typename Exception>
[[noreturn]] void throw_exception(Exception&& exception)
{
throw exception;
}
} //namespace details
} //namespace gsl
#define GSL_CONTRACT_CHECK(type, cond) \ #define GSL_CONTRACT_CHECK(type, cond) \
(GSL_LIKELY(cond) ? static_cast<void>(0) \ (GSL_LIKELY(cond) ? static_cast<void>(0) \
: throw gsl::fail_fast("GSL: " type " failure at " __FILE__ \ : gsl::throw_exception(gsl::fail_fast("GSL: " type " failure at " __FILE__ \
": " GSL_STRINGIFY(__LINE__))) ": " GSL_STRINGIFY(__LINE__))))
#elif defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION) #elif defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION)
#define GSL_CONTRACT_CHECK(type, cond) (GSL_LIKELY(cond) ? static_cast<void>(0) : std::terminate()) #define GSL_CONTRACT_CHECK(type, cond) (GSL_LIKELY(cond) ? static_cast<void>(0) : std::terminate())
namespace gsl
{
namespace details
{
template <typename Exception>
[[noreturn]] void throw_exception(Exception&& exception)
{
static_cast<void>(exception);
std::terminate();
}
} //namespace details
} //namespace gsl
#define GSL_CONTRACT_CHECK(type, cond) \
(GSL_LIKELY(cond) ? static_cast<void>(0) : std::terminate())
#elif defined(GSL_UNENFORCED_ON_CONTRACT_VIOLATION) #elif defined(GSL_UNENFORCED_ON_CONTRACT_VIOLATION)
#define GSL_CONTRACT_CHECK(type, cond) GSL_ASSUME(cond) #define GSL_CONTRACT_CHECK(type, cond) GSL_ASSUME(cond)

View File

@ -121,9 +121,9 @@ template <class T, class U>
inline T narrow(U u) inline T narrow(U u)
{ {
T t = narrow_cast<T>(u); T t = narrow_cast<T>(u);
if (static_cast<U>(t) != u) throw narrowing_error(); if (static_cast<U>(t) != u) gsl::details::throw_exception(narrowing_error());
if (!details::is_same_signedness<T, U>::value && ((t < T{}) != (u < U{}))) if (!details::is_same_signedness<T, U>::value && ((t < T{}) != (u < U{})))
throw narrowing_error(); gsl::details::throw_exception(narrowing_error());
return t; return t;
} }