util: backport scope_exit & co. from the Library Fundamentals TS v3

Implementation taken from scope-lite by Martin Moene,
commit 197cd4240069b2b8c393ad0d9eabdee601b606b4

Change-Id: I872b6821504b3270ebdc4c48b7255731fb2efc57
diff --git a/COPYING.md b/COPYING.md
index 7b140e4..b72dd74 100644
--- a/COPYING.md
+++ b/COPYING.md
@@ -12,6 +12,9 @@
 - optional-lite by Martin Moene is licensed under the
   [Boost Software License 1.0](https://github.com/martinmoene/optional-lite/blob/master/LICENSE.txt)
 
+- scope-lite by Martin Moene is licensed under the
+  [Boost Software License 1.0](https://github.com/martinmoene/scope-lite/blob/master/LICENSE.txt)
+
 - variant-lite by Martin Moene is licensed under the
   [Boost Software License 1.0](https://github.com/martinmoene/variant-lite/blob/master/LICENSE.txt)
 
diff --git a/docs/doxygen.conf.in b/docs/doxygen.conf.in
index c6aeeb0..8e31136 100644
--- a/docs/doxygen.conf.in
+++ b/docs/doxygen.conf.in
@@ -2128,12 +2128,6 @@
 
 EXTERNAL_PAGES         = YES
 
-# The PERL_PATH should be the absolute path and name of the perl script
-# interpreter (i.e. the result of 'which perl').
-# The default file (with absolute path) is: /usr/bin/perl.
-
-PERL_PATH              = /usr/bin/perl
-
 #---------------------------------------------------------------------------
 # Configuration options related to the dot tool
 #---------------------------------------------------------------------------
@@ -2147,15 +2141,6 @@
 
 CLASS_DIAGRAMS         = YES
 
-# You can define message sequence charts within doxygen comments using the \msc
-# command. Doxygen will then run the mscgen tool (see:
-# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
-# documentation. The MSCGEN_PATH tag allows you to specify the directory where
-# the mscgen tool resides. If left empty the tool is assumed to be found in the
-# default search path.
-
-MSCGEN_PATH            =
-
 # You can include diagrams made with dia in doxygen documentation. Doxygen will
 # then run dia to produce the diagram and insert it in the documentation. The
 # DIA_PATH tag allows you to specify the directory where the dia binary resides.
diff --git a/ndn-cxx/face.cpp b/ndn-cxx/face.cpp
index 3843bc6..3da96b7 100644
--- a/ndn-cxx/face.cpp
+++ b/ndn-cxx/face.cpp
@@ -24,6 +24,7 @@
 #include "ndn-cxx/impl/face-impl.hpp"
 #include "ndn-cxx/net/face-uri.hpp"
 #include "ndn-cxx/security/signing-helpers.hpp"
+#include "ndn-cxx/util/scope.hpp"
 #include "ndn-cxx/util/time.hpp"
 
 // NDN_LOG_INIT(ndn.Face) is declared in face-impl.hpp
@@ -261,32 +262,28 @@
     m_ioService.reset(); // ensure that run()/poll() will do some work
   }
 
-  try {
-    if (timeout < time::milliseconds::zero()) {
-      // do not block if timeout is negative, but process pending events
-      m_ioService.poll();
-      return;
-    }
+  auto onThrow = make_scope_fail([this] { m_impl->shutdown(); });
 
-    if (timeout > time::milliseconds::zero()) {
-      m_impl->m_processEventsTimeoutEvent = m_impl->m_scheduler.schedule(timeout,
-        [&io = m_ioService, &work = m_impl->m_ioServiceWork] {
-          io.stop();
-          work.reset();
-        });
-    }
-
-    if (keepThread) {
-      // work will ensure that m_ioService is running until work object exists
-      m_impl->m_ioServiceWork = make_unique<boost::asio::io_service::work>(m_ioService);
-    }
-
-    m_ioService.run();
+  if (timeout < 0_ms) {
+    // do not block if timeout is negative, but process pending events
+    m_ioService.poll();
+    return;
   }
-  catch (...) {
-    m_impl->shutdown();
-    throw;
+
+  if (timeout > 0_ms) {
+    m_impl->m_processEventsTimeoutEvent = m_impl->m_scheduler.schedule(timeout,
+      [&io = m_ioService, &work = m_impl->m_ioServiceWork] {
+        io.stop();
+        work.reset();
+      });
   }
+
+  if (keepThread) {
+    // work will ensure that m_ioService is running until work object exists
+    m_impl->m_ioServiceWork = make_unique<boost::asio::io_service::work>(m_ioService);
+  }
+
+  m_ioService.run();
 }
 
 void
diff --git a/ndn-cxx/security/transform/private-key.cpp b/ndn-cxx/security/transform/private-key.cpp
index f5c9360..242bcba 100644
--- a/ndn-cxx/security/transform/private-key.cpp
+++ b/ndn-cxx/security/transform/private-key.cpp
@@ -30,9 +30,9 @@
 #include "ndn-cxx/security/key-params.hpp"
 #include "ndn-cxx/encoding/buffer-stream.hpp"
 #include "ndn-cxx/util/random.hpp"
+#include "ndn-cxx/util/scope.hpp"
 
 #include <boost/lexical_cast.hpp>
-#include <boost/scope_exit.hpp>
 #include <cstring>
 
 #define ENSURE_PRIVATE_KEY_LOADED(key) \
@@ -493,12 +493,11 @@
   default:
     NDN_THROW(std::invalid_argument("Unsupported EC key length " + to_string(keySize)));
   }
-  if (eckey == nullptr)
+  if (eckey == nullptr) {
     NDN_THROW(Error("Failed to set EC curve"));
+  }
 
-  BOOST_SCOPE_EXIT(&eckey) {
-    EC_KEY_free(eckey);
-  } BOOST_SCOPE_EXIT_END
+  auto guard = make_scope_exit([eckey] { EC_KEY_free(eckey); });
 
 #if OPENSSL_VERSION_NUMBER < 0x1010000fL
   EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE);
diff --git a/ndn-cxx/util/nonstd/scope-lite.hpp b/ndn-cxx/util/nonstd/scope-lite.hpp
new file mode 100644
index 0000000..8a4c346
--- /dev/null
+++ b/ndn-cxx/util/nonstd/scope-lite.hpp
@@ -0,0 +1,1434 @@
+//
+// Copyright (c) 2020-2020 Martin Moene
+//
+// https://github.com/martinmoene/scope-lite
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// C++ standard libraries extensions, version 3
+// https://en.cppreference.com/w/cpp/experimental/lib_extensions_3
+
+#ifndef NONSTD_SCOPE_LITE_HPP
+#define NONSTD_SCOPE_LITE_HPP
+
+#define scope_lite_MAJOR  0
+#define scope_lite_MINOR  1
+#define scope_lite_PATCH  0
+
+#define scope_lite_VERSION  scope_STRINGIFY(scope_lite_MAJOR) "." scope_STRINGIFY(scope_lite_MINOR) "." scope_STRINGIFY(scope_lite_PATCH)
+
+#define scope_STRINGIFY(  x )  scope_STRINGIFY_( x )
+#define scope_STRINGIFY_( x )  #x
+
+// scope-lite configuration:
+
+#define scope_SCOPE_DEFAULT  0
+#define scope_SCOPE_NONSTD   1
+#define scope_SCOPE_STD      2
+
+#if !defined( scope_CONFIG_SELECT_SCOPE )
+# define scope_CONFIG_SELECT_SCOPE  ( scope_HAVE_STD_SCOPE ? scope_SCOPE_STD : scope_SCOPE_NONSTD )
+#endif
+
+// #if !defined( scope_CONFIG_STRICT )
+// # define scope_CONFIG_STRICT  0
+// #endif
+
+// C++ language version detection (C++20 is speculative):
+// Note: VC14.0/1900 (VS2015) lacks too much from C++14.
+
+#ifndef   scope_CPLUSPLUS
+# if defined(_MSVC_LANG ) && !defined(__clang__)
+#  define scope_CPLUSPLUS  (_MSC_VER == 1900 ? 201103L : _MSVC_LANG )
+# else
+#  define scope_CPLUSPLUS  __cplusplus
+# endif
+#endif
+
+#define scope_CPP98_OR_GREATER  ( scope_CPLUSPLUS >= 199711L )
+#define scope_CPP11_OR_GREATER  ( scope_CPLUSPLUS >= 201103L )
+#define scope_CPP14_OR_GREATER  ( scope_CPLUSPLUS >= 201402L )
+#define scope_CPP17_OR_GREATER  ( scope_CPLUSPLUS >= 201703L )
+#define scope_CPP20_OR_GREATER  ( scope_CPLUSPLUS >= 202000L )
+
+// Use C++yy <scope> if available and requested:
+
+#if scope_CPP20_OR_GREATER && defined(__has_include )
+# if __has_include( <scope> )
+#  define scope_HAVE_STD_SCOPE  1
+# else
+#  define scope_HAVE_STD_SCOPE  0
+# endif
+#else
+# define  scope_HAVE_STD_SCOPE  0
+#endif
+
+#define  scope_USES_STD_SCOPE  ( (scope_CONFIG_SELECT_SCOPE == scope_SCOPE_STD) || ((scope_CONFIG_SELECT_SCOPE == scope_SCOPE_DEFAULT) && scope_HAVE_STD_SCOPE) )
+
+//
+// Using std <scope>:
+//
+
+#if scope_USES_STD_SCOPE
+
+#include <scope>
+
+namespace nonstd
+{
+    using std::scope_exit;
+    using std::scope_fail;
+    using std::scope_success;
+    using std::unique_resource;
+
+    using std::make_scope_exit;
+    using std::make_scope_fail;
+    using std::make_scope_success;
+    using std::make_unique_resource_checked;
+}
+
+#else // scope_USES_STD_SCOPE
+
+// half-open range [lo..hi):
+#define scope_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) )
+
+// Compiler versions:
+//
+// MSVC++  6.0  _MSC_VER == 1200  scope_COMPILER_MSVC_VERSION ==  60  (Visual Studio 6.0)
+// MSVC++  7.0  _MSC_VER == 1300  scope_COMPILER_MSVC_VERSION ==  70  (Visual Studio .NET 2002)
+// MSVC++  7.1  _MSC_VER == 1310  scope_COMPILER_MSVC_VERSION ==  71  (Visual Studio .NET 2003)
+// MSVC++  8.0  _MSC_VER == 1400  scope_COMPILER_MSVC_VERSION ==  80  (Visual Studio 2005)
+// MSVC++  9.0  _MSC_VER == 1500  scope_COMPILER_MSVC_VERSION ==  90  (Visual Studio 2008)
+// MSVC++ 10.0  _MSC_VER == 1600  scope_COMPILER_MSVC_VERSION == 100  (Visual Studio 2010)
+// MSVC++ 11.0  _MSC_VER == 1700  scope_COMPILER_MSVC_VERSION == 110  (Visual Studio 2012)
+// MSVC++ 12.0  _MSC_VER == 1800  scope_COMPILER_MSVC_VERSION == 120  (Visual Studio 2013)
+// MSVC++ 14.0  _MSC_VER == 1900  scope_COMPILER_MSVC_VERSION == 140  (Visual Studio 2015)
+// MSVC++ 14.1  _MSC_VER >= 1910  scope_COMPILER_MSVC_VERSION == 141  (Visual Studio 2017)
+// MSVC++ 14.2  _MSC_VER >= 1920  scope_COMPILER_MSVC_VERSION == 142  (Visual Studio 2019)
+
+#if defined(_MSC_VER ) && !defined(__clang__)
+# define scope_COMPILER_MSVC_VER      (_MSC_VER )
+# define scope_COMPILER_MSVC_VERSION  (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) )
+#else
+# define scope_COMPILER_MSVC_VER      0
+# define scope_COMPILER_MSVC_VERSION  0
+#endif
+
+// Courtesy of https://github.com/gsl-lite/gsl-lite
+// AppleClang  7.0.0  __apple_build_version__ ==  7000172  scope_COMPILER_APPLECLANG_VERSION ==  700  (Xcode 7.0, 7.0.1)          (LLVM 3.7.0)
+// AppleClang  7.0.0  __apple_build_version__ ==  7000176  scope_COMPILER_APPLECLANG_VERSION ==  700  (Xcode 7.1)                 (LLVM 3.7.0)
+// AppleClang  7.0.2  __apple_build_version__ ==  7000181  scope_COMPILER_APPLECLANG_VERSION ==  702  (Xcode 7.2, 7.2.1)          (LLVM 3.7.0)
+// AppleClang  7.3.0  __apple_build_version__ ==  7030029  scope_COMPILER_APPLECLANG_VERSION ==  730  (Xcode 7.3)                 (LLVM 3.8.0)
+// AppleClang  7.3.0  __apple_build_version__ ==  7030031  scope_COMPILER_APPLECLANG_VERSION ==  730  (Xcode 7.3.1)               (LLVM 3.8.0)
+// AppleClang  8.0.0  __apple_build_version__ ==  8000038  scope_COMPILER_APPLECLANG_VERSION ==  800  (Xcode 8.0)                 (LLVM 3.9.0)
+// AppleClang  8.0.0  __apple_build_version__ ==  8000042  scope_COMPILER_APPLECLANG_VERSION ==  800  (Xcode 8.1, 8.2, 8.2.1)     (LLVM 3.9.0)
+// AppleClang  8.1.0  __apple_build_version__ ==  8020038  scope_COMPILER_APPLECLANG_VERSION ==  810  (Xcode 8.3)                 (LLVM 3.9.0)
+// AppleClang  8.1.0  __apple_build_version__ ==  8020041  scope_COMPILER_APPLECLANG_VERSION ==  810  (Xcode 8.3.1)               (LLVM 3.9.0)
+// AppleClang  8.1.0  __apple_build_version__ ==  8020042  scope_COMPILER_APPLECLANG_VERSION ==  810  (Xcode 8.3.2, 8.3.3)        (LLVM 3.9.0)
+// AppleClang  9.0.0  __apple_build_version__ ==  9000037  scope_COMPILER_APPLECLANG_VERSION ==  900  (Xcode 9.0)                 (LLVM 4.0.0?)
+// AppleClang  9.0.0  __apple_build_version__ ==  9000038  scope_COMPILER_APPLECLANG_VERSION ==  900  (Xcode 9.1)                 (LLVM 4.0.0?)
+// AppleClang  9.0.0  __apple_build_version__ ==  9000039  scope_COMPILER_APPLECLANG_VERSION ==  900  (Xcode 9.2)                 (LLVM 4.0.0?)
+// AppleClang  9.1.0  __apple_build_version__ ==  9020039  scope_COMPILER_APPLECLANG_VERSION ==  910  (Xcode 9.3, 9.3.1)          (LLVM 5.0.2?)
+// AppleClang  9.1.0  __apple_build_version__ ==  9020039  scope_COMPILER_APPLECLANG_VERSION ==  910  (Xcode 9.4, 9.4.1)          (LLVM 5.0.2?)
+// AppleClang 10.0.0  __apple_build_version__ == 10001145  scope_COMPILER_APPLECLANG_VERSION == 1000  (Xcode 10.0, 10.1)          (LLVM 6.0.1?)
+// AppleClang 10.0.1  __apple_build_version__ == 10010046  scope_COMPILER_APPLECLANG_VERSION == 1001  (Xcode 10.2, 10.2.1, 10.3)  (LLVM 7.0.0?)
+// AppleClang 11.0.0  __apple_build_version__ == 11000033  scope_COMPILER_APPLECLANG_VERSION == 1100  (Xcode 11.1, 11.2, 11.3)    (LLVM 8.0.0?)
+
+#define scope_COMPILER_VERSION( major, minor, patch )  ( 10 * ( 10 * (major) + (minor) ) + (patch) )
+
+#if defined( __apple_build_version__ )
+# define scope_COMPILER_APPLECLANG_VERSION scope_COMPILER_VERSION( __clang_major__, __clang_minor__, __clang_patchlevel__ )
+# define scope_COMPILER_CLANG_VERSION 0
+#elif defined( __clang__ )
+# define scope_COMPILER_APPLECLANG_VERSION 0
+# define scope_COMPILER_CLANG_VERSION scope_COMPILER_VERSION( __clang_major__, __clang_minor__, __clang_patchlevel__ )
+#else
+# define scope_COMPILER_APPLECLANG_VERSION 0
+# define scope_COMPILER_CLANG_VERSION 0
+#endif
+
+#if defined(__GNUC__) && !defined(__clang__)
+# define scope_COMPILER_GNUC_VERSION  scope_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
+#else
+# define scope_COMPILER_GNUC_VERSION  0
+#endif
+
+// Presence of language and library features:
+
+#define scope_HAVE( feature )  ( scope_HAVE_##feature )
+
+#ifdef _HAS_CPP0X
+# define scope_HAS_CPP0X  _HAS_CPP0X
+#else
+# define scope_HAS_CPP0X  0
+#endif
+
+#define scope_CPP11_90   (scope_CPP11_OR_GREATER || scope_COMPILER_MSVC_VER >= 1500)
+#define scope_CPP11_100  (scope_CPP11_OR_GREATER || scope_COMPILER_MSVC_VER >= 1600)
+#define scope_CPP11_110  (scope_CPP11_OR_GREATER || scope_COMPILER_MSVC_VER >= 1700)
+#define scope_CPP11_120  (scope_CPP11_OR_GREATER || scope_COMPILER_MSVC_VER >= 1800)
+#define scope_CPP11_140  (scope_CPP11_OR_GREATER || scope_COMPILER_MSVC_VER >= 1900)
+
+#define scope_CPP14_000  (scope_CPP14_OR_GREATER)
+
+#define scope_CPP17_000  (scope_CPP17_OR_GREATER)
+#define scope_CPP17_140  (scope_CPP17_OR_GREATER || scope_COMPILER_MSVC_VER >= 1900)
+
+// Presence of C++11 language features:
+
+#define scope_HAVE_CONSTEXPR_11           scope_CPP11_140
+// #define scope_HAVE_ENUM_CLASS             scope_CPP11_110
+#define scope_HAVE_IS_DEFAULT             scope_CPP11_120
+#define scope_HAVE_IS_DELETE              scope_CPP11_120
+#define scope_HAVE_NOEXCEPT               scope_CPP11_140
+#define scope_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG  scope_CPP11_120
+#define scope_HAVE_STATIC_ASSERT          scope_CPP11_90
+#define scope_HAVE_TRAILING_RETURN_TYPE   scope_CPP11_120
+#define scope_HAVE_VALUE_INITIALIZATION   scope_CPP11_120
+
+// Presence of C++14 language features:
+
+#define scope_HAVE_CONSTEXPR_14           scope_CPP14_000
+
+// Presence of C++17 language features:
+
+#define scope_HAVE_DEDUCTION_GUIDES       scope_CPP17_000
+#define scope_HAVE_NODISCARD              scope_CPP17_000
+
+// Presence of C++11 library features:
+
+#define scope_HAVE_IS_TRIVIAL             scope_CPP11_110
+#define scope_HAVE_IS_TRIVIALLY_COPYABLE  scope_CPP11_110 && !scope_BETWEEN(scope_COMPILER_GNUC_VERSION, 1, 500) // GCC >= 5
+#define scope_HAVE_IS_CONSTRUCTIBLE       scope_CPP11_110
+#define scope_HAVE_IS_COPY_CONSTRUCTIBLE  scope_CPP11_110
+#define scope_HAVE_IS_MOVE_CONSTRUCTIBLE  scope_CPP11_110
+#define scope_HAVE_IS_NOTHROW_CONSTRUCTIBLE scope_CPP11_110
+#define scope_HAVE_IS_NOTHROW_MOVE_CONSTRUCTIBLE scope_CPP11_110
+#define scope_HAVE_IS_COPY_ASSIGNABLE     scope_CPP11_110
+#define scope_HAVE_IS_NOTHROW_ASSIGNABLE  scope_CPP11_110
+#define scope_HAVE_IS_NOTHROW_MOVE_ASSIGNABLE  scope_CPP11_110
+
+#define scope_HAVE_REMOVE_CV              scope_CPP11_90
+#define scope_HAVE_REMOVE_REFERENCE       scope_CPP11_90
+
+#define scope_HAVE_TYPE_TRAITS            scope_CPP11_110
+#define scope_HAVE_TR1_TYPE_TRAITS        ((!! scope_COMPILER_GNUC_VERSION ) && scope_CPP11_OR_GREATER)
+
+#define scope_HAVE_DECAY                  scope_CPP11_110
+#define scope_HAVE_DECAY_TR1              scope_HAVE_TR1_TYPE_TRAITS
+
+#define scope_HAVE_IS_SAME                scope_HAVE_TYPE_TRAITS
+#define scope_HAVE_IS_SAME_TR1            scope_HAVE_TR1_TYPE_TRAITS
+
+// #define scope_HAVE_CSTDINT                scope_CPP11_90
+
+// Presence of C++14 library features:
+
+// Presence of C++17 library features:
+
+#define scope_HAVE_UNCAUGHT_EXCEPTIONS    scope_CPP17_140
+
+// Presence of C++ language features:
+
+#if scope_HAVE_CONSTEXPR_11
+# define scope_constexpr constexpr
+#else
+# define scope_constexpr /*constexpr*/
+#endif
+
+#if scope_HAVE_CONSTEXPR_14
+# define scope_constexpr14 constexpr
+#else
+# define scope_constexpr14 /*constexpr*/
+#endif
+
+#if scope_HAVE( IS_DELETE )
+# define scope_is_delete = delete
+# define scope_is_delete_access public
+#else
+# define scope_is_delete
+# define scope_is_delete_access private
+#endif
+
+#if scope_HAVE_NOEXCEPT
+# define scope_noexcept noexcept
+# define scope_noexcept_op(expr) noexcept(expr)
+#else
+# define scope_noexcept /*noexcept*/
+# define scope_noexcept_op(expr) /*noexcept(expr)*/
+#endif
+
+#if scope_HAVE_NODISCARD
+# define scope_nodiscard [[nodiscard]]
+#else
+# define scope_nodiscard /*[[nodiscard]]*/
+#endif
+
+#if scope_HAVE_STATIC_ASSERT
+# define scope_static_assert(expr, msg) static_assert((expr), msg)
+#else
+# define scope_static_assert(expr, msg) /*static_assert((expr), msg)*/
+#endif
+
+// Select C++98 version
+
+#define scope_USE_POST_CPP98_VERSION  scope_CPP11_100
+
+// Additional includes:
+
+#include <exception>    // exception, terminate(), uncaught_exceptions()
+#include <limits>       // std::numeric_limits<>
+#include <utility>      // move(), forward<>(), swap()
+
+#if scope_HAVE_TYPE_TRAITS
+# include <type_traits>
+#elif scope_HAVE_TR1_TYPE_TRAITS
+# include <tr1/type_traits>
+#endif
+
+// Method enabling (return type):
+
+#if scope_HAVE( TYPE_TRAITS )
+# define scope_ENABLE_IF_R_(VA, R)  typename std::enable_if< (VA), R >::type
+#else
+# define scope_ENABLE_IF_R_(VA, R)  R
+#endif
+
+// Method enabling (funtion template argument):
+
+#if scope_HAVE( TYPE_TRAITS ) && scope_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG )
+// VS 2013 seems to have trouble with SFINAE for default non-type arguments:
+# if !scope_BETWEEN( scope_COMPILER_MSVC_VERSION, 1, 140 )
+#  define scope_ENABLE_IF_(VA) , typename std::enable_if< ( VA ), int >::type = 0
+# else
+#  define scope_ENABLE_IF_(VA) , typename = typename std::enable_if< ( VA ), ::nonstd::scope::enabler >::type
+# endif
+#else
+# define  scope_ENABLE_IF_(VA)
+#endif
+
+// Declare __cxa_get_globals() or equivalent in namespace nonstd::scope for uncaught_exceptions():
+
+#if !scope_HAVE( UNCAUGHT_EXCEPTIONS )
+# if scope_COMPILER_MSVC_VERSION                                // libstl :)
+    namespace nonstd { namespace scope { extern "C" char * __cdecl _getptd(); }}
+# elif scope_COMPILER_CLANG_VERSION || scope_COMPILER_GNUC_VERSION || scope_COMPILER_APPLECLANG_VERSION
+# if defined(__GLIBCXX__) || defined(__GLIBCPP__)               // libstdc++: prototype from cxxabi.h
+#   include  <cxxabi.h>
+# elif !defined(BOOST_CORE_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED_)   // libc++: prototype from Boost?
+# if defined(__FreeBSD__) || defined(__OpenBSD__)
+    namespace __cxxabiv1 { struct __cxa_eh_globals; extern "C" __cxa_eh_globals * __cxa_get_globals(); }
+# else
+    namespace __cxxabiv1 { struct __cxa_eh_globals; extern "C" __cxa_eh_globals * __cxa_get_globals() scope_noexcept; }
+# endif
+# endif
+    namespace nonstd { namespace scope { using ::__cxxabiv1::__cxa_get_globals; }}
+# endif // scope_COMPILER_MSVC_VERSION
+#endif // !scope_HAVE( UNCAUGHT_EXCEPTIONS )
+
+// Namespace nonstd:
+
+namespace nonstd {
+namespace scope {
+
+// for bit_ENABLE_IF_():
+
+/*enum*/ class enabler{};
+
+// C++11 emulation:
+
+namespace std11 {
+
+template< class T, T v > struct integral_constant { enum { value = v }; };
+template< bool B       > struct bool_constant : integral_constant<bool, B>{};
+
+typedef bool_constant< true  > true_type;
+typedef bool_constant< false > false_type;
+
+template <class T> struct is_reference      : false_type{};
+template <class T> struct is_reference<T&>  : true_type {};
+#if scope_CPP11_100
+template <class T> struct is_reference<T&&> : true_type {};
+#endif
+
+template< class T > struct remove_pointer                    { typedef T type; };
+template< class T > struct remove_pointer<T*>                { typedef T type; };
+template< class T > struct remove_pointer<T* const>          { typedef T type; };
+template< class T > struct remove_pointer<T* volatile>       { typedef T type; };
+template< class T > struct remove_pointer<T* const volatile> { typedef T type; };
+
+template<bool B, class T, class F>
+struct conditional { typedef T type; };
+
+template<class T, class F>
+struct conditional<false, T, F> { typedef F type; };
+
+#if scope_HAVE( DECAY )
+    using std::decay;
+#elif scope_HAVE( DECAY_TR1 )
+    using std::tr1::decay;
+#else
+    template< class T > struct decay{ typedef T type; };
+#endif
+
+#if scope_HAVE( IS_TRIVIAL )
+    using std::is_trivial;
+#else
+    template< class T > struct is_trivial : std11::true_type{};
+#endif
+
+#if scope_HAVE( IS_TRIVIALLY_COPYABLE )
+    using std::is_trivially_copyable;
+#else
+    template< class T > struct is_trivially_copyable : std11::true_type{};
+#endif
+
+#if scope_HAVE( IS_CONSTRUCTIBLE )
+    using std::is_constructible;
+#else
+    template< class T > struct is_constructible : std11::true_type{};
+#endif
+
+#if scope_HAVE( IS_COPY_CONSTRUCTIBLE )
+    using std::is_copy_constructible;
+#else
+    template< class T > struct is_copy_constructible : std11::true_type{};
+#endif
+
+#if scope_HAVE( IS_MOVE_CONSTRUCTIBLE )
+    using std::is_move_constructible;
+#else
+    template< class T > struct is_move_constructible : std11::true_type{};
+#endif
+
+#if scope_HAVE( IS_NOTHROW_CONSTRUCTIBLE )
+    using std::is_nothrow_constructible;
+#else
+    template< class T, class U > struct is_nothrow_constructible : std11::true_type{};
+#endif
+
+#if scope_HAVE( IS_NOTHROW_COPY_CONSTRUCTIBLE )
+    using std::is_nothrow_copy_constructible;
+#else
+    template< class T > struct is_nothrow_copy_constructible : std11::true_type{};
+#endif
+
+#if scope_HAVE( IS_NOTHROW_MOVE_CONSTRUCTIBLE )
+    using std::is_nothrow_move_constructible;
+#else
+    template< class T > struct is_nothrow_move_constructible : std11::true_type{};
+#endif
+
+#if scope_HAVE( IS_COPY_ASSIGNABLE )
+    using std::is_copy_assignable;
+#else
+    template< class T > struct is_copy_assignable : std11::true_type{};
+#endif
+
+#if scope_HAVE( IS_NOTHROW_ASSIGNABLE )
+    using std::is_nothrow_assignable;
+#else
+    template< class T, class U > struct is_nothrow_assignable : std11::true_type{};
+#endif
+
+#if scope_HAVE( IS_NOTHROW_MOVE_ASSIGNABLE )
+    using std::is_nothrow_move_assignable;
+#else
+    template< class T > struct is_nothrow_move_assignable : std11::true_type{};
+#endif
+
+#if scope_HAVE( IS_SAME )
+    using std::is_same;
+#elif scope_HAVE( IS_SAME_TR1 )
+    using std::tr1::is_same;
+#else
+    template< class T, class U > struct is_same : std11::true_type{};
+#endif
+
+#if scope_HAVE( REMOVE_CV )
+    using std::remove_cv;
+#else
+    template< class T > struct remove_cv{ typedef T type; };
+#endif
+
+#if scope_HAVE( REMOVE_REFERENCE )
+    using std::remove_reference;
+#else
+    template< class T > struct remove_reference{ typedef T type; };
+#endif
+
+
+#if scope_HAVE( REFERENCE_WRAPPER )
+    using std::reference_wrapper;
+#else
+    template< class T > struct reference_wrapper{ typedef T type; };
+#endif
+
+} // namepsace std11
+
+// C++14 emulation:
+
+namespace std14 {
+
+#if scope_CPP11_100
+#if scope_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG )
+template< class T, class U = T >
+#else
+template< class T, class U /*= T*/ >
+#endif
+scope_constexpr14 T exchange( T & obj, U && new_value )
+{
+    T old_value = std::move( obj );
+    obj = std::forward<U>( new_value );
+    return old_value;
+}
+#else
+// C++98 version?
+#endif
+
+} // namespace std14
+
+// C++17 emulation (uncaught_exceptions):
+
+namespace std17 {
+
+template< typename T >
+inline int to_int( T x ) scope_noexcept
+{
+    return static_cast<int>( x );
+}
+
+#if scope_HAVE( UNCAUGHT_EXCEPTIONS )
+
+inline int uncaught_exceptions() scope_noexcept
+{
+    return to_int( std::uncaught_exceptions() );
+}
+
+#elif scope_COMPILER_MSVC_VERSION
+
+inline int uncaught_exceptions() scope_noexcept
+{
+    return to_int( *reinterpret_cast<const unsigned*>(_getptd() + (sizeof(void*) == 8 ? 0x100 : 0x90) ) );
+}
+
+#elif scope_COMPILER_CLANG_VERSION || scope_COMPILER_GNUC_VERSION || scope_COMPILER_APPLECLANG_VERSION
+
+inline int uncaught_exceptions() scope_noexcept
+{
+    return to_int( *reinterpret_cast<const unsigned*>(
+        reinterpret_cast<const unsigned char*>(__cxa_get_globals()) + sizeof(void*) ) );
+}
+
+#endif // scope_HAVE( UNCAUGHT_EXCEPTIONS )
+
+} // namespace std17
+
+// C++20 emulation:
+
+namespace std20 {
+
+template< class T >
+struct remove_cvref
+{
+    typedef typename std11::remove_cv<typename std11::remove_reference<T>::type>::type type;
+};
+
+template< class T, class U >
+struct same_as : std11::integral_constant<bool, std11::is_same<T,U>::value && std11::is_same<U,T>::value> {};
+
+template< class T >
+struct type_identity { typedef T type; };
+
+} // namepsace std20
+
+//
+// For reference:
+//
+
+#if 0
+
+template< class EF>
+class scope_exit;
+
+template< class EF>
+class scope_fail;
+
+template< class EF>
+class scope_success;
+
+template<class R,class D>
+class unique_resource;
+
+// special factory function:
+
+template<class R,class D, class S=R>
+unique_resource<decay_t<R>, decay_t<D>>
+make_unique_resource_checked(R&& r, S const& invalid, D&& d)
+noexcept(is_nothrow_constructible_v<decay_t<R>, R> && is_nothrow_constructible_v<decay_t<D>, D>);
+
+// optional factory functions (should at least be present for LFTS3):
+
+template< class EF>
+scope_exit<decay_t<EF>>
+make_scope_exit(EF&& exit_function) ;
+
+template< class EF>
+scope_fail<decay_t<EF>>
+make_scope_fail(EF&& exit_function) ;
+
+template< class EF>
+scope_success<decay_t<EF>>
+make_scope_success(EF&& exit_function) ;
+
+#endif // reference
+
+#if scope_USE_POST_CPP98_VERSION
+
+//
+// Post-C++98 version:
+//
+
+template< typename T >
+T && conditional_forward( T && t, std11::true_type )
+{
+    return std::forward<T>( t );
+}
+
+template< typename T >
+T const & conditional_forward( T && t, std11::false_type )
+{
+    return t;
+}
+
+template< typename T >
+T && conditional_move( T && t, std11::true_type )
+{
+    return std::move( t );
+}
+
+template< typename T >
+T const & conditional_move( T && t, std11::false_type )
+{
+    return t;
+}
+
+// template< typename FE, typename Fn >
+// struct to_argument_type<EF,Fn>
+// {
+// };
+
+// scope_exit:
+
+template< class EF >
+class scope_exit
+{
+public:
+    template< class Fn
+        scope_ENABLE_IF_((
+            !std11::is_same<typename std20::remove_cvref<Fn>::type, scope_exit>::value
+            && std11::is_constructible<EF, Fn>::value
+        ))
+    >
+    explicit scope_exit( Fn&& fn )
+    scope_noexcept_op
+    ((
+        std11::is_nothrow_constructible<EF, Fn>::value
+        || std11::is_nothrow_constructible<EF, Fn&>::value
+    ))
+        : exit_function(
+//            to_argument_type<EF,Fn>( std::forward<Fn>(fn) ) )
+            conditional_forward<Fn>( std::forward<Fn>(fn)
+                , std11::bool_constant< std11::is_nothrow_constructible<EF, Fn>::value >() ) )
+        , execute_on_destruction( true )
+    {}
+
+    scope_exit( scope_exit && other )
+    scope_noexcept_op
+    ((
+        std11::is_nothrow_move_constructible<EF>::value
+        || std11::is_nothrow_copy_constructible<EF>::value
+    ))
+        : exit_function( std::forward<EF>( other.exit_function ) )
+        , execute_on_destruction( other.execute_on_destruction )
+    {
+        other.release();
+    }
+
+    ~scope_exit() scope_noexcept
+    {
+        if ( execute_on_destruction )
+            exit_function();
+    }
+
+    void release() scope_noexcept
+    {
+        execute_on_destruction = false;
+    }
+
+scope_is_delete_access:
+    scope_exit( scope_exit const & ) scope_is_delete;
+
+    scope_exit & operator=( scope_exit const & ) scope_is_delete;
+    scope_exit & operator=( scope_exit &&      ) scope_is_delete;
+
+private:
+    EF exit_function;
+    bool execute_on_destruction; // { true };
+};
+
+// scope_fail:
+
+template< class EF >
+class scope_fail
+{
+public:
+    template< class Fn
+        scope_ENABLE_IF_((
+            !std11::is_same<typename std20::remove_cvref<Fn>::type, scope_fail>::value
+            && std11::is_constructible<EF, Fn>::value
+        ))
+    >
+    explicit scope_fail( Fn&& fn )
+    scope_noexcept_op
+    ((
+        std11::is_nothrow_constructible<EF, Fn>::value
+        || std11::is_nothrow_constructible<EF, Fn&>::value
+    ))
+        : exit_function(
+            conditional_forward<Fn>( std::forward<Fn>(fn)
+            , std11::bool_constant< std11::is_nothrow_constructible<EF, Fn>::value >() ) )
+        , uncaught_on_creation( std17::uncaught_exceptions() )
+    {}
+
+    scope_fail( scope_fail && other )
+    scope_noexcept_op
+    ((
+        std11::is_nothrow_move_constructible<EF>::value
+        || std11::is_nothrow_copy_constructible<EF>::value
+    ))
+        : exit_function( std::forward<EF>( other.exit_function ) )
+        , uncaught_on_creation( other.uncaught_on_creation )
+    {
+        other.release();
+    }
+
+    ~scope_fail() scope_noexcept
+    {
+        if ( uncaught_on_creation < std17::uncaught_exceptions() )
+            exit_function();
+    }
+
+    void release() scope_noexcept
+    {
+        uncaught_on_creation = std::numeric_limits<int>::max();
+    }
+
+scope_is_delete_access:
+    scope_fail( scope_fail const & ) scope_is_delete;
+
+    scope_fail & operator=( scope_fail const & ) scope_is_delete;
+    scope_fail & operator=( scope_fail &&      ) scope_is_delete;
+
+private:
+    EF exit_function;
+    int uncaught_on_creation; // { std17::uncaught_exceptions() };
+};
+
+// scope_success:
+
+template< class EF >
+class scope_success
+{
+public:
+    template< class Fn
+        scope_ENABLE_IF_((
+            !std11::is_same<typename std20::remove_cvref<Fn>::type, scope_success>::value
+            && std11::is_constructible<EF, Fn>::value
+        ))
+    >
+    explicit scope_success( Fn&& fn )
+    scope_noexcept_op
+    ((
+        std11::is_nothrow_constructible<EF, Fn>::value
+        || std11::is_nothrow_constructible<EF, Fn&>::value
+    ))
+        : exit_function(
+            conditional_forward<Fn>( std::forward<Fn>(fn)
+            , std11::bool_constant< std11::is_nothrow_constructible<EF, Fn>::value >() ) )
+        , uncaught_on_creation( std17::uncaught_exceptions() )
+    {}
+
+    scope_success( scope_success && other )
+    scope_noexcept_op
+    ((
+        std11::is_nothrow_move_constructible<EF>::value
+        || std11::is_nothrow_copy_constructible<EF>::value
+    ))
+        : exit_function( std::forward<EF>( other.exit_function ) )
+        , uncaught_on_creation( other.uncaught_on_creation )
+    {
+        other.release();
+    }
+
+    ~scope_success() scope_noexcept
+    {
+        if ( uncaught_on_creation >= std17::uncaught_exceptions() )
+            exit_function();
+    }
+
+    void release() scope_noexcept
+    {
+        uncaught_on_creation = -1;
+    }
+
+scope_is_delete_access:
+    scope_success( scope_success const & ) scope_is_delete;
+
+    scope_success & operator=( scope_success const & ) scope_is_delete;
+    scope_success & operator=( scope_success &&      ) scope_is_delete;
+
+private:
+    EF exit_function;
+    int uncaught_on_creation; // { std17::uncaught_exceptions() };
+};
+
+#if scope_HAVE( DEDUCTION_GUIDES )
+template< class EF > scope_exit(EF) -> scope_exit<EF>;
+template< class EF > scope_fail(EF) -> scope_fail<EF>;
+template< class EF > scope_success(EF) -> scope_success<EF>;
+#endif
+
+// optional factory functions (should at least be present for LFTS3):
+
+template< class EF >
+scope_exit<typename std11::decay<EF>::type>
+make_scope_exit( EF && exit_function )
+{
+    return scope_exit<typename std11::decay<EF>::type>( std::forward<EF>( exit_function ) );
+}
+
+template< class EF >
+scope_fail<typename std11::decay<EF>::type>
+make_scope_fail( EF && exit_function )
+{
+    return scope_fail<typename std11::decay<EF>::type>( std::forward<EF>( exit_function ) );
+}
+
+template< class EF >
+scope_success<typename std11::decay<EF>::type>
+make_scope_success( EF && exit_function )
+{
+    return scope_success<typename std11::decay<EF>::type>( std::forward<EF>( exit_function ) );
+}
+
+// unique_resource:
+
+template< class R, class D >
+class unique_resource
+{
+private:
+    scope_static_assert(
+        (  std11::is_move_constructible<R>::value && std11::is_nothrow_move_constructible<R>::value )
+        || std11::is_copy_constructible<R>::value
+        , "resource must be nothrow_move_constructible or copy_constructible"
+    );
+
+    scope_static_assert(
+          (std11::is_move_constructible<R>::value && std11::is_nothrow_move_constructible<D>::value )
+        || std11::is_copy_constructible<D>::value
+        , "deleter must be nothrow_move_constructible or copy_constructible"
+    );
+
+    typedef typename std11::conditional<
+        std11::is_reference<R>::value
+        , typename std11::reference_wrapper< typename std11::remove_reference<R>::type >::type
+        , R
+    >::type R1;
+
+public:
+    // This overload only participates in overload resolution if:
+    // - std::is_default_constructible_v<R>
+    // - && std::is_default_constructible_v<D>
+
+    unique_resource()
+#if scope_HAVE( VALUE_INITIALIZATION )
+        : resource{}
+        , deleter{}
+        , execute_on_reset{ false }
+#else
+        : resource()
+        , deleter()
+        , execute_on_reset( false )
+#endif
+    {}
+
+    // construction: note extra execute default parameter
+
+    template< class RR, class DD
+#if scope_BETWEEN( scope_COMPILER_MSVC_VERSION, 120, 130 )
+        scope_ENABLE_IF_(( true
+        //  &&  std11::is_constructible<R1, RR>::value
+            &&  std11::is_constructible<D , DD>::value
+        //  && (std11::is_nothrow_constructible<R1, RR>::value || std11::is_constructible<R1, RR&>::value )
+            &&  std11::is_nothrow_constructible<D, DD>::value  || std11::is_constructible<D, DD&>::value
+        ))
+#else
+        scope_ENABLE_IF_(( true
+            &&  std11::is_constructible<R1, RR>::value
+            &&  std11::is_constructible<D , DD>::value
+            && (std11::is_nothrow_constructible<R1, RR>::value || std11::is_constructible<R1, RR&>::value )
+            &&  std11::is_nothrow_constructible<D, DD>::value  || std11::is_constructible<D, DD&>::value
+        ))
+#endif
+    >
+    unique_resource( RR && r, DD && d, bool execute = true )
+        scope_noexcept_op((
+            ( std11::is_nothrow_constructible<R1, RR>::value || std11::is_nothrow_constructible<R1, RR&>::value )
+            && ( std11::is_nothrow_constructible<D, DD>::value || std11::is_nothrow_constructible<D, DD&>::value )
+        ))
+        : resource( conditional_forward<RR>( std::forward<RR>(r)
+            , std11::bool_constant< std11::is_nothrow_constructible<R1, RR>::value >() ) )
+        , deleter( ( conditional_forward<DD>( std::forward<DD>(d)
+            , std11::bool_constant< std11::is_nothrow_constructible<D, DD>::value >() ) ) )
+        , execute_on_reset( execute )
+    {}
+
+    // TODO:Move constructor.
+    // The stored resource handle is initialized from the one of other, using std::move if
+    // std::is_nothrow_move_constructible_v<RS> is true.
+
+    // If initialization of the stored resource handle throws an exception, other is not modified.
+
+    // Then, the deleter is initialized with the one of other, using std::move if
+    // std::is_nothrow_move_constructible_v<D> is true.
+
+    // If initialization of the deleter throws an exception and std::is_nothrow_move_constructible_v<RS> is true and
+    // other owns the resource, calls the deleter of other with res_ to dispose the resource, then calls other.release().
+
+    // After construction, the constructed unique_resource owns its resource if and only if other owned the resource before
+    // the construction, and other is set to not own the resource.
+
+    unique_resource( unique_resource && other )
+        scope_noexcept_op(
+            std11::is_nothrow_move_constructible<R1>::value && std11::is_nothrow_move_constructible<D>::value
+        )
+    try
+        : resource( conditional_move( std::move(other.resource), typename std11::bool_constant< std11::is_nothrow_move_assignable<R>::value >() ) )
+        , deleter(  conditional_move( std::move(other.deleter ), typename std11::bool_constant< std11::is_nothrow_move_constructible<D>::value >() ) )
+        , execute_on_reset( std14::exchange( other.execute_on_reset, false ) )
+    {}
+    catch(...)
+    {
+        if ( other.execute_on_reset && std::is_nothrow_move_constructible<R>::value )
+        {
+            other.get_deleter()( this->get() );
+            other.release();
+        }
+    }
+
+    ~unique_resource()
+    {
+        reset();
+    }
+
+private:
+    // assign_rd( r, is_nothrow_move_assignable_v<R>, is_nothrow_move_assignable_v<D> ):
+
+    void assign_rd( unique_resource && other, std11::true_type, std11::true_type )
+    {
+        resource = std::move( other.resource );
+        deleter  = std::move( other.deleter );
+    }
+
+    void assign_rd( unique_resource && other, std11::true_type, std11::false_type )
+    {
+        resource = std::move( other.resource );
+        deleter  = other.deleter;
+    }
+
+    void assign_rd( unique_resource && other, std11::false_type, std11::true_type )
+    {
+        deleter  = std::move( other.deleter );
+        resource = other.resource;
+    }
+
+    void assign_rd( unique_resource && other, std11::false_type, std11::false_type )
+    {
+        resource = other.resource;
+        deleter  = other.deleter;
+    }
+
+public:
+    unique_resource & operator=( unique_resource && other )
+        scope_noexcept_op(
+            std11::is_nothrow_move_assignable<R1>::value && std11::is_nothrow_move_assignable<D>::value
+        )
+    {
+        scope_static_assert(
+            std11::is_nothrow_move_assignable<R>::value || std11::is_copy_assignable<R>::value
+            , "The resource must be nothrow-move assignable, or copy assignable"
+        );
+
+        scope_static_assert(
+            std11::is_nothrow_move_assignable<D>::value || std11::is_copy_assignable<D>::value
+            , "The deleter must be nothrow-move assignable, or copy assignable");
+
+        if ( &other != this )
+        {
+            reset();
+            assign_rd(
+                std::move( other )
+                , typename std11::bool_constant< std11::is_nothrow_move_assignable<R>::value >()
+                , typename std11::bool_constant< std11::is_nothrow_move_assignable<D>::value >()
+            );
+            execute_on_reset = std14::exchange( other.execute_on_reset, false );
+        }
+
+        return *this;
+    }
+
+    void reset() scope_noexcept
+    {
+        if ( execute_on_reset )
+        {
+            execute_on_reset = false;
+            get_deleter()( get() );
+        }
+    }
+
+    template< class RR >
+    void reset( RR && r )
+#if scope_CPP11_110
+    {
+        auto && guard = make_scope_fail( [&, this]{ get_deleter()(r); } ); // -Wunused-variable on clang
+
+        reset();
+        resource = conditional_forward<RR>( std::forward<RR>(r)
+            , std11::bool_constant< std11::is_nothrow_assignable<R1, RR>::value >() );
+        execute_on_reset = true;
+    }
+#else // scope_CPP11_110
+    try
+    {
+        reset();
+        resource = conditional_forward<RR>( std::forward<RR>(r)
+            , std11::bool_constant< std11::is_nothrow_assignable<R1, RR>::value >() );
+        execute_on_reset = true;
+    }
+    catch(...)
+    {
+        this->get_deleter()(r);
+    }
+#endif // scope_CPP11_110
+
+    void release() scope_noexcept
+    {
+        execute_on_reset = false;
+    }
+
+    R1 const & get() const scope_noexcept
+    {
+        return resource;
+    }
+
+    // VC120/VS2013 produces ICE:
+
+#if scope_HAVE( TRAILING_RETURN_TYPE ) && !scope_BETWEEN( scope_COMPILER_MSVC_VERSION, 120, 130 )
+    template< class RR=R >
+    auto operator*() const scope_noexcept ->
+        scope_ENABLE_IF_R_(
+            std::is_pointer<RR>::value && !std::is_void<typename std::remove_pointer<RR>::type>::value
+            , typename std::add_lvalue_reference<typename std::remove_pointer<R>::type>::type
+        )
+#else
+    typename std::add_lvalue_reference<typename std::remove_pointer<R>::type>::type
+    operator*() const scope_noexcept
+#endif
+    {
+        return *get();
+    }
+
+    // VC120/VS2013 produces ICE:
+
+#if scope_HAVE( TRAILING_RETURN_TYPE ) && !scope_BETWEEN( scope_COMPILER_MSVC_VERSION, 120, 130 )
+    template< class RR=R >
+    auto operator->() const scope_noexcept -> scope_ENABLE_IF_R_( std::is_pointer<RR>::value, R )
+#else
+    R operator->() const scope_noexcept
+#endif
+    {
+        return get();
+    }
+
+    D const & get_deleter() const scope_noexcept
+    {
+        return deleter;
+    }
+
+scope_is_delete_access:
+	unique_resource & operator=( unique_resource const & ) scope_is_delete;
+	unique_resource( unique_resource const & ) scope_is_delete;
+
+private:
+    R1 resource;
+    D deleter;
+    bool execute_on_reset;
+};
+
+#if scope_HAVE( DEDUCTION_GUIDES )
+template< typename R, typename D >
+unique_resource(R, D) -> unique_resource<R, D>;
+#endif
+
+// special factory function make_unique_resource_checked():
+
+#if scope_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG
+
+template< class R, class D, class S = typename std11::decay<R>::type >
+unique_resource
+<
+    typename std11::decay<R>::type
+    , typename std11::decay<D>::type
+>
+//make_unique_resource_checked( R && resource, typename std20::type_identity<S>::type const & invalid, D && deleter )
+make_unique_resource_checked( R && resource, S const & invalid, D && deleter )
+scope_noexcept_op
+((
+    std11::is_nothrow_constructible<typename std11::decay<R>::type, R>::value
+    && std11::is_nothrow_constructible<typename std11::decay<D>::type, D>::value
+))
+{
+    return unique_resource<typename std11::decay<R>::type, typename std11::decay<D>::type>(
+        std::forward<R>( resource ), std::forward<D>( deleter ), !bool( resource == invalid ) );
+}
+
+#else // scope_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG
+
+// avoid default template arguments:
+
+template< class R, class D >
+unique_resource
+<
+    typename std11::decay<R>::type
+    , typename std11::decay<D>::type
+>
+make_unique_resource_checked( R && resource, R const & invalid, D && deleter )
+scope_noexcept_op
+((
+    std11::is_nothrow_constructible<typename std11::decay<R>::type, R>::value
+    && std11::is_nothrow_constructible<typename std11::decay<D>::type, D>::value
+))
+{
+    return unique_resource<typename std11::decay<R>::type, typename std11::decay<D>::type>(
+        std::forward<R>( resource ), std::forward<D>( deleter ), !bool( resource == invalid ) );
+}
+
+template< class R, class D, class S >
+unique_resource
+<
+    typename std11::decay<R>::type
+    , typename std11::decay<D>::type
+>
+make_unique_resource_checked( R && resource, S const & invalid, D && deleter )
+scope_noexcept_op
+((
+    std11::is_nothrow_constructible<typename std11::decay<R>::type, R>::value
+    && std11::is_nothrow_constructible<typename std11::decay<D>::type, D>::value
+))
+{
+    return unique_resource<typename std11::decay<R>::type, typename std11::decay<D>::type>(
+        std::forward<R>( resource ), std::forward<D>( deleter ), !bool( resource == invalid ) );
+}
+
+#endif // scope_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG
+
+#else // #if scope_USE_POST_CPP98_VERSION
+
+//
+// C++98 version:
+//
+
+struct on_exit_policy
+{
+    mutable bool invoke_;
+
+    on_exit_policy()
+        : invoke_( true )
+    {}
+
+    on_exit_policy( on_exit_policy const & other )
+        : invoke_( other.invoke_ )
+    {
+        other.invoke_ = false;
+    }
+
+    void release()
+    {
+        invoke_ = false;
+    }
+
+    bool perform()
+    {
+        return invoke_;
+    }
+};
+
+struct on_fail_policy
+{
+    mutable int ucount_;
+
+    on_fail_policy()
+        : ucount_( std17::uncaught_exceptions() )
+    {}
+
+    on_fail_policy( on_fail_policy const & other )
+        : ucount_( other.ucount_ )
+    {
+        other.ucount_ = std::numeric_limits<int>::max();
+    }
+
+    void release()
+    {
+        ucount_ = std::numeric_limits<int>::max();
+    }
+
+    bool perform()
+    {
+        return ucount_ < std17::uncaught_exceptions();
+    }
+};
+
+struct on_success_policy
+{
+    mutable int ucount_;
+
+    on_success_policy()
+        : ucount_( std17::uncaught_exceptions() )
+    {}
+
+    on_success_policy( on_success_policy const & other )
+        : ucount_( other.ucount_ )
+    {
+        other.ucount_ = -1;
+    }
+
+    void release()
+    {
+        ucount_ = -1;
+    }
+
+    bool perform()
+    {
+        return ucount_ >= std17::uncaught_exceptions();
+    }
+};
+
+template< typename Policy >
+class scope_guard : public Policy
+{
+public:
+    typedef void (*Action)();
+
+    template< typename Fn >
+    scope_guard( Fn action )
+        : Policy()
+        , action_( action )
+    {}
+
+    scope_guard( scope_guard const & other )
+        : Policy( other )
+        , action_( other.action_ )
+    {}
+
+    virtual ~scope_guard()
+    {
+        if ( this->perform() )
+            action_();
+    }
+
+private:
+    scope_guard & operator=( scope_guard const & );
+
+private:
+    Action action_;
+};
+
+class scope_exit : public scope_guard< on_exit_policy >
+{
+public:
+    template< typename Fn >
+    scope_exit( Fn action ) : scope_guard( action ) {}
+};
+
+class scope_fail : public scope_guard< on_fail_policy >
+{
+public:
+    template< typename Fn >
+    scope_fail( Fn action ) : scope_guard( action ) {}
+};
+
+class scope_success : public scope_guard< on_success_policy >
+{
+public:
+    template< typename Fn >
+    scope_success( Fn action ) : scope_guard( action ) {}
+};
+
+// unique_resource (C++98):
+
+template< class R, class D >
+class unique_resource
+{
+public:
+    unique_resource()
+        : resource()
+        , deleter()
+        , execute_on_reset( false )
+    {}
+
+    template< class RR, class DD >
+    unique_resource( RR const & r, DD const & d, bool execute = true )
+    : resource( r )
+    , deleter(  d )
+    , execute_on_reset( execute )
+    {}
+
+    // 'move' construction
+
+    unique_resource( unique_resource const & other )
+    : resource( other.resource )
+    , deleter(  other.deleter  )
+    , execute_on_reset( other.execute_on_reset )
+    {
+        other.execute_on_reset = false; // other.release();
+    }
+
+    ~unique_resource()
+    {
+        reset();
+    }
+
+    // 'move' assignment
+
+    unique_resource & operator=( unique_resource const & other )
+    {
+        reset();
+        resource = other.resource;
+        deleter = other.deleter;
+        execute_on_reset = other.execute_on_reset;
+        other.execute_on_reset = false; // other.release();
+
+        return *this;
+    }
+
+    void reset()
+    {
+        if ( execute_on_reset )
+        {
+            execute_on_reset = false;
+            get_deleter()( get() );
+        }
+    }
+
+    template< class RR >
+    void reset( RR const & r )
+    try
+    {
+        reset();
+		resource = r;
+        execute_on_reset = true;
+    }
+    catch(...)
+    {
+        this->get_deleter()( r );
+    }
+
+    void release()
+    {
+        execute_on_reset = false;
+    }
+
+    R const & get() const
+    {
+        return resource;
+    }
+
+    typename std11::remove_pointer<R>::type &
+    operator*() const
+    {
+        return *get();
+    }
+
+    R operator->() const
+    {
+        return get();
+    }
+
+    D const & get_deleter() const
+    {
+        return deleter;
+    }
+
+private:
+    // using R1 = conditional_t< is_reference_v<R>, reference_wrapper<remove_reference_t<R>>, R >; // exposition only
+    // typedef R R1;
+    R resource;
+    D deleter;
+    mutable bool execute_on_reset;
+};
+
+template< class EF >
+scope_exit make_scope_exit( EF action )
+{
+    return scope_exit( action );
+}
+
+template< class EF >
+scope_fail make_scope_fail( EF action )
+{
+    return scope_fail( action );
+}
+
+template< class EF >
+scope_success make_scope_success( EF action )
+{
+    return scope_success( action );
+}
+
+template< class R, class D, class S >
+unique_resource
+<
+    typename std11::decay<R>::type
+    , typename std11::decay<D>::type
+>
+make_unique_resource_checked( R const & resource, S const & invalid, D const & deleter )
+{
+    return unique_resource<typename std11::decay<R>::type, typename std11::decay<D>::type>(
+        resource,deleter, !bool( resource == invalid ) );
+}
+
+#endif // #if scope_USE_POST_CPP98_VERSION
+
+}} // namespace nonstd::scope
+
+//
+// Make type available in namespace nonstd:
+//
+
+namespace nonstd
+{
+    using scope::scope_exit;
+    using scope::scope_fail;
+    using scope::scope_success;
+    using scope::unique_resource;
+
+    using scope::make_scope_exit;
+    using scope::make_scope_fail;
+    using scope::make_scope_success;
+    using scope::make_unique_resource_checked;
+}
+
+#endif // scope_USES_STD_SCOPE
+
+#endif // NONSTD_SCOPE_LITE_HPP
diff --git a/ndn-cxx/util/scheduler.cpp b/ndn-cxx/util/scheduler.cpp
index 7b2b56a..8a542c3 100644
--- a/ndn-cxx/util/scheduler.cpp
+++ b/ndn-cxx/util/scheduler.cpp
@@ -21,8 +21,7 @@
 
 #include "ndn-cxx/util/scheduler.hpp"
 #include "ndn-cxx/util/impl/steady-timer.hpp"
-
-#include <boost/scope_exit.hpp>
+#include "ndn-cxx/util/scope.hpp"
 
 namespace ndn {
 namespace scheduler {
@@ -145,15 +144,12 @@
     return;
   }
 
+  auto guard = make_scope_exit([this] {
+    m_isEventExecuting = false;
+    scheduleNext();
+  });
   m_isEventExecuting = true;
 
-  // ASan reports a stack-use-after-scope on armhf when
-  // BOOST_SCOPE_EXIT_ALL is used in place of BOOST_SCOPE_EXIT
-  BOOST_SCOPE_EXIT(this_) {
-    this_->m_isEventExecuting = false;
-    this_->scheduleNext();
-  } BOOST_SCOPE_EXIT_END
-
   // process all expired events
   auto now = time::steady_clock::now();
   while (!m_queue.empty()) {
diff --git a/ndn-cxx/util/scope.hpp b/ndn-cxx/util/scope.hpp
new file mode 100644
index 0000000..2a2edd9
--- /dev/null
+++ b/ndn-cxx/util/scope.hpp
@@ -0,0 +1,42 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2020 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_CXX_UTIL_SCOPE_HPP
+#define NDN_CXX_UTIL_SCOPE_HPP
+
+#define scope_CONFIG_SELECT_SCOPE scope_SCOPE_NONSTD
+#include "ndn-cxx/util/nonstd/scope-lite.hpp"
+
+namespace ndn {
+
+using ::nonstd::scope_exit;
+using ::nonstd::scope_fail;
+using ::nonstd::scope_success;
+using ::nonstd::unique_resource;
+
+using ::nonstd::make_scope_exit;
+using ::nonstd::make_scope_fail;
+using ::nonstd::make_scope_success;
+using ::nonstd::make_unique_resource_checked;
+
+} // namespace ndn
+
+#endif // NDN_CXX_UTIL_SCOPE_HPP
diff --git a/ndn-cxx/util/signal/signal.hpp b/ndn-cxx/util/signal/signal.hpp
index fe2aee5..b579fa9 100644
--- a/ndn-cxx/util/signal/signal.hpp
+++ b/ndn-cxx/util/signal/signal.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2019 Regents of the University of California.
+ * Copyright (c) 2013-2020 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -22,6 +22,7 @@
 #ifndef NDN_UTIL_SIGNAL_SIGNAL_HPP
 #define NDN_UTIL_SIGNAL_SIGNAL_HPP
 
+#include "ndn-cxx/util/scope.hpp"
 #include "ndn-cxx/util/signal/connection.hpp"
 
 #include <list>
@@ -219,30 +220,23 @@
     return;
   }
 
-  auto it = m_slots.begin();
-  auto last = std::prev(m_slots.end());
+  auto guard = make_scope_exit([this] { m_isExecuting = false; });
   m_isExecuting = true;
 
-  try {
-    bool isLast = false;
-    while (!isLast) {
-      m_currentSlot = it;
-      isLast = it == last;
+  auto it = m_slots.begin();
+  auto last = std::prev(m_slots.end());
+  bool isLast = false;
+  while (!isLast) {
+    m_currentSlot = it;
+    isLast = it == last;
 
-      m_currentSlot->handler(args...);
+    m_currentSlot->handler(args...);
 
-      if (m_currentSlot == m_slots.end())
-        it = m_slots.erase(it);
-      else
-        ++it;
-    }
+    if (m_currentSlot == m_slots.end())
+      it = m_slots.erase(it);
+    else
+      ++it;
   }
-  catch (...) {
-    m_isExecuting = false;
-    throw;
-  }
-
-  m_isExecuting = false;
 }
 
 template<typename Owner, typename ...TArgs>
diff --git a/tests/unit/security/certificate-fetcher-offline.t.cpp b/tests/unit/security/certificate-fetcher-offline.t.cpp
index e3ca483..ac1e9ee 100644
--- a/tests/unit/security/certificate-fetcher-offline.t.cpp
+++ b/tests/unit/security/certificate-fetcher-offline.t.cpp
@@ -21,12 +21,11 @@
 
 #include "ndn-cxx/security/certificate-fetcher-offline.hpp"
 #include "ndn-cxx/security/validation-policy-simple-hierarchy.hpp"
+#include "ndn-cxx/util/scope.hpp"
 
 #include "tests/boost-test.hpp"
 #include "tests/unit/security/validator-fixture.hpp"
 
-#include <boost/scope_exit.hpp>
-
 namespace ndn {
 namespace security {
 inline namespace v2 {
@@ -49,15 +48,13 @@
 
 BOOST_FIXTURE_TEST_SUITE(TestCertificateFetcherOffline, CertificateFetcherOfflineFixture)
 
-typedef boost::mpl::vector<Interest, Data> Packets;
+using Packets = boost::mpl::vector<Interest, Data>;
 
 BOOST_AUTO_TEST_CASE_TEMPLATE(Validate, Packet, Packets)
 {
   // Can't set CanBePrefix on Interests in this test case because of template
   // TODO: Remove in #4582
-  BOOST_SCOPE_EXIT(void) {
-    Interest::s_errorIfCanBePrefixUnset = true;
-  } BOOST_SCOPE_EXIT_END
+  auto guard = make_scope_exit([] { Interest::s_errorIfCanBePrefixUnset = true; });
   Interest::s_errorIfCanBePrefixUnset = false;
 
   Packet unsignedPacket("/Security/ValidatorFixture/Sub1/Packet");
diff --git a/tests/unit/security/validation-policy-simple-hierarchy.t.cpp b/tests/unit/security/validation-policy-simple-hierarchy.t.cpp
index 958f005..a6b6fdc 100644
--- a/tests/unit/security/validation-policy-simple-hierarchy.t.cpp
+++ b/tests/unit/security/validation-policy-simple-hierarchy.t.cpp
@@ -20,12 +20,12 @@
  */
 
 #include "ndn-cxx/security/validation-policy-simple-hierarchy.hpp"
+#include "ndn-cxx/util/scope.hpp"
 
 #include "tests/boost-test.hpp"
 #include "tests/unit/security/validator-fixture.hpp"
 
 #include <boost/mpl/vector.hpp>
-#include <boost/scope_exit.hpp>
 
 namespace ndn {
 namespace security {
@@ -38,15 +38,13 @@
 BOOST_FIXTURE_TEST_SUITE(TestValidationPolicySimpleHierarchy,
                          HierarchicalValidatorFixture<ValidationPolicySimpleHierarchy>)
 
-typedef boost::mpl::vector<Interest, Data> Packets;
+using Packets = boost::mpl::vector<Interest, Data>;
 
 BOOST_AUTO_TEST_CASE_TEMPLATE(Validate, Packet, Packets)
 {
   // Can't set CanBePrefix on Interests in this test case because of template
   // TODO: Remove in #4582
-  BOOST_SCOPE_EXIT(void) {
-    Interest::s_errorIfCanBePrefixUnset = true;
-  } BOOST_SCOPE_EXIT_END
+  auto guard = make_scope_exit([] { Interest::s_errorIfCanBePrefixUnset = true; });
   Interest::s_errorIfCanBePrefixUnset = false;
 
   Packet unsignedPacket("/Security/ValidatorFixture/Sub1/Sub2/Packet");
diff --git a/tools/ndnsec/export.cpp b/tools/ndnsec/export.cpp
index 79bea3d..2b6d528 100644
--- a/tools/ndnsec/export.cpp
+++ b/tools/ndnsec/export.cpp
@@ -24,8 +24,7 @@
 
 #include "ndn-cxx/security/impl/openssl.hpp"
 #include "ndn-cxx/util/io.hpp"
-
-#include <boost/scope_exit.hpp>
+#include "ndn-cxx/util/scope.hpp"
 
 namespace ndn {
 namespace ndnsec {
@@ -42,11 +41,9 @@
   std::string output;
   std::string password;
 
-  // ASan reports a stack-use-after-scope on armhf when
-  // BOOST_SCOPE_EXIT_ALL is used in place of BOOST_SCOPE_EXIT
-  BOOST_SCOPE_EXIT(&password) {
+  auto guard = make_scope_exit([&password] {
     OPENSSL_cleanse(&password.front(), password.size());
-  } BOOST_SCOPE_EXIT_END
+  });
 
   po::options_description visibleOptDesc(
     "Usage: ndnsec export [-h] [-o FILE] [-P PASSPHRASE] [-i|-k|-c] NAME\n"
diff --git a/tools/ndnsec/import.cpp b/tools/ndnsec/import.cpp
index fa67a44..9dab73f 100644
--- a/tools/ndnsec/import.cpp
+++ b/tools/ndnsec/import.cpp
@@ -24,8 +24,7 @@
 
 #include "ndn-cxx/security/impl/openssl.hpp"
 #include "ndn-cxx/util/io.hpp"
-
-#include <boost/scope_exit.hpp>
+#include "ndn-cxx/util/scope.hpp"
 
 namespace ndn {
 namespace ndnsec {
@@ -38,11 +37,9 @@
   std::string input;
   std::string password;
 
-  // ASan reports a stack-use-after-scope on armhf when
-  // BOOST_SCOPE_EXIT_ALL is used in place of BOOST_SCOPE_EXIT
-  BOOST_SCOPE_EXIT(&password) {
+  auto guard = make_scope_exit([&password] {
     OPENSSL_cleanse(&password.front(), password.size());
-  } BOOST_SCOPE_EXIT_END
+  });
 
   po::options_description description(
     "Usage: ndnsec import [-h] [-P PASSPHRASE] [-i] FILE\n"