build: switch to C++14

Replace our homegrown implementation of optional (based
on Boost.Optional) with optional-lite by Martin Moene.

Change-Id: I4632cbc7c705a94af0b85a335515e3430bf3cb1f
Refs: #3076
diff --git a/src/common.hpp b/src/common.hpp
index 7b5d4c8..6de1e07 100644
--- a/src/common.hpp
+++ b/src/common.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2017 Regents of the University of California.
+ * Copyright (c) 2013-2018 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -44,15 +44,14 @@
 #define NDN_CXX_PROTECTED_WITH_TESTS_ELSE_PRIVATE private
 #endif
 
-// require C++11
-#if __cplusplus < 201103L && !defined(__GXX_EXPERIMENTAL_CXX0X__)
-#  error "ndn-cxx applications must be compiled using the C++11 standard (-std=c++11)"
+// require C++14
+#if __cplusplus < 201402L
+#error "ndn-cxx applications must be compiled using the C++14 standard (-std=c++14)"
 #endif
 
 #include <algorithm>
 #include <cstddef>
 #include <cstdint>
-#include <exception>
 #include <functional>
 #include <iosfwd>
 #include <limits>
@@ -68,9 +67,8 @@
 using std::shared_ptr;
 using std::unique_ptr;
 using std::weak_ptr;
-using std::bad_weak_ptr;
 using std::make_shared;
-using std::enable_shared_from_this;
+using std::make_unique;
 
 using std::static_pointer_cast;
 using std::dynamic_pointer_cast;
diff --git a/src/data.hpp b/src/data.hpp
index 2368017..d70f509 100644
--- a/src/data.hpp
+++ b/src/data.hpp
@@ -30,9 +30,9 @@
 
 namespace ndn {
 
-/** @brief Represents a Data packet
+/** @brief Represents a Data packet.
  */
-class Data : public PacketBase, public enable_shared_from_this<Data>
+class Data : public PacketBase, public std::enable_shared_from_this<Data>
 {
 public:
   class Error : public tlv::Error
@@ -234,14 +234,14 @@
   /** @deprecated Use @c getFinalBlock
    *  @sa MetaInfo::getFinalBlockId
    */
-  NDN_CXX_DEPRECATED
+  [[deprecated("use getFinalBlock")]]
   name::Component
   getFinalBlockId() const;
 
   /** @deprecated Use @c setFinalBlock
    *  @sa MetaInfo::setFinalBlockId
    */
-  NDN_CXX_DEPRECATED
+  [[deprecated("use setFinalBlock")]]
   Data&
   setFinalBlockId(const name::Component& finalBlockId);
 
diff --git a/src/encoding/tlv.hpp b/src/encoding/tlv.hpp
index 10961c5..fc664c6 100644
--- a/src/encoding/tlv.hpp
+++ b/src/encoding/tlv.hpp
@@ -106,7 +106,8 @@
   Any                       = 19,
 };
 
-constexpr int NameComponent NDN_CXX_DEPRECATED = GenericNameComponent;
+[[deprecated("use GenericNameComponent")]]
+constexpr int NameComponent = GenericNameComponent;
 
 enum SignatureTypeValue : uint16_t {
   DigestSha256 = 0,
@@ -519,7 +520,6 @@
   }
 }
 
-
 } // namespace tlv
 } // namespace ndn
 
diff --git a/src/interest.hpp b/src/interest.hpp
index 5fc1c42..7d0705e 100644
--- a/src/interest.hpp
+++ b/src/interest.hpp
@@ -39,7 +39,7 @@
 
 /** @brief Represents an Interest packet.
  */
-class Interest : public PacketBase, public enable_shared_from_this<Interest>
+class Interest : public PacketBase, public std::enable_shared_from_this<Interest>
 {
 public:
   class Error : public tlv::Error
@@ -272,21 +272,21 @@
 public: // Selectors (deprecated)
   /** @brief Check if Interest has any selector present.
    */
-  NDN_CXX_DEPRECATED
+  [[deprecated]]
   bool
   hasSelectors() const
   {
     return !m_selectors.empty();
   }
 
-  NDN_CXX_DEPRECATED
+  [[deprecated]]
   const Selectors&
   getSelectors() const
   {
     return m_selectors;
   }
 
-  NDN_CXX_DEPRECATED
+  [[deprecated]]
   Interest&
   setSelectors(const Selectors& selectors)
   {
@@ -295,14 +295,14 @@
     return *this;
   }
 
-  NDN_CXX_DEPRECATED
+  [[deprecated]]
   int
   getMinSuffixComponents() const
   {
     return m_selectors.getMinSuffixComponents();
   }
 
-  NDN_CXX_DEPRECATED
+  [[deprecated]]
   Interest&
   setMinSuffixComponents(int minSuffixComponents)
   {
@@ -311,14 +311,14 @@
     return *this;
   }
 
-  NDN_CXX_DEPRECATED
+  [[deprecated]]
   int
   getMaxSuffixComponents() const
   {
     return m_selectors.getMaxSuffixComponents();
   }
 
-  NDN_CXX_DEPRECATED
+  [[deprecated]]
   Interest&
   setMaxSuffixComponents(int maxSuffixComponents)
   {
@@ -327,14 +327,14 @@
     return *this;
   }
 
-  NDN_CXX_DEPRECATED
+  [[deprecated]]
   const KeyLocator&
   getPublisherPublicKeyLocator() const
   {
     return m_selectors.getPublisherPublicKeyLocator();
   }
 
-  NDN_CXX_DEPRECATED
+  [[deprecated]]
   Interest&
   setPublisherPublicKeyLocator(const KeyLocator& keyLocator)
   {
@@ -343,14 +343,14 @@
     return *this;
   }
 
-  NDN_CXX_DEPRECATED
+  [[deprecated]]
   const Exclude&
   getExclude() const
   {
     return m_selectors.getExclude();
   }
 
-  NDN_CXX_DEPRECATED
+  [[deprecated]]
   Interest&
   setExclude(const Exclude& exclude)
   {
@@ -359,14 +359,14 @@
     return *this;
   }
 
-  NDN_CXX_DEPRECATED
+  [[deprecated]]
   int
   getChildSelector() const
   {
     return m_selectors.getChildSelector();
   }
 
-  NDN_CXX_DEPRECATED
+  [[deprecated]]
   Interest&
   setChildSelector(int childSelector)
   {
diff --git a/src/meta-info.hpp b/src/meta-info.hpp
index 911b1a3..3c3c59e 100644
--- a/src/meta-info.hpp
+++ b/src/meta-info.hpp
@@ -34,7 +34,7 @@
 const time::milliseconds DEFAULT_FRESHNESS_PERIOD = time::milliseconds::zero();
 
 /**
- * An MetaInfo holds the meta info which is signed inside the data packet.
+ * A MetaInfo holds the meta info which is signed inside the data packet.
  *
  * The class allows experimentation with application-defined meta information blocks,
  * which slightly violates NDN-TLV specification.  When using the application-defined
@@ -138,7 +138,7 @@
    *  If FinalBlockId element is omitted, returns a default-constructed @c name::Component.
    *  This is indistinguishable from having an empty GenericNameComponent as FinalBlockId.
    */
-  NDN_CXX_DEPRECATED
+  [[deprecated("use getFinalBlock")]]
   name::Component
   getFinalBlockId() const
   {
@@ -151,7 +151,7 @@
    *  Passing a default-constructed @c name::Component removes FinalBlockId element.
    *  This API does not support adding an empty GenericNameComponent as FinalBlockId.
    */
-  NDN_CXX_DEPRECATED
+  [[deprecated("use setFinalBlock")]]
   MetaInfo&
   setFinalBlockId(const name::Component& finalBlockId);
 
diff --git a/src/mgmt/status-dataset-context.cpp b/src/mgmt/status-dataset-context.cpp
index 2abbaa7..c8671cd 100644
--- a/src/mgmt/status-dataset-context.cpp
+++ b/src/mgmt/status-dataset-context.cpp
@@ -86,7 +86,7 @@
                    makeBinaryBlock(tlv::Content, m_buffer->buf(), m_buffer->size()),
                    m_expiry, false);
 
-      m_buffer = std::make_shared<EncodingBuffer>();
+      m_buffer = make_shared<EncodingBuffer>();
     }
   }
 }
diff --git a/src/transport/stream-transport-impl.hpp b/src/transport/stream-transport-impl.hpp
index c8f1527..d2c232b 100644
--- a/src/transport/stream-transport-impl.hpp
+++ b/src/transport/stream-transport-impl.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2017 Regents of the University of California.
+ * Copyright (c) 2013-2018 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -31,13 +31,13 @@
 
 namespace ndn {
 
-/** \brief implementation detail of a Boost.Asio-based stream-oriented transport
+/** \brief Implementation detail of a Boost.Asio-based stream-oriented transport.
  *  \tparam BaseTransport a subclass of Transport
- *  \tparam Protocol a Boost.Asio stream-oriented protocol, including boost::asio::ip::tcp
- *                   and boost::asio::local::stream_protocol
+ *  \tparam Protocol a Boost.Asio stream-oriented protocol, e.g. boost::asio::ip::tcp
+ *                   or boost::asio::local::stream_protocol
  */
 template<typename BaseTransport, typename Protocol>
-class StreamTransportImpl : public enable_shared_from_this<StreamTransportImpl<BaseTransport, Protocol>>
+class StreamTransportImpl : public std::enable_shared_from_this<StreamTransportImpl<BaseTransport, Protocol>>
 {
 public:
   typedef StreamTransportImpl<BaseTransport, Protocol> Impl;
diff --git a/src/util/backports-optional.hpp b/src/util/backports-optional.hpp
deleted file mode 100644
index 73e1068..0000000
--- a/src/util/backports-optional.hpp
+++ /dev/null
@@ -1,333 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2013-2018 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.
- */
-
-/** \file
- *  \brief C++17 std::optional backport implemented using boost::optional
- *  \sa http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/n4594.pdf section 20.6
- *  \sa http://en.cppreference.com/w/cpp/utility/optional
- *
- *  Differences from C++17 include:
- *  \li No constructor and operator= taking a T&&,
- *      because boost::optional lacks a move constructor as of Boost 1.54
- *  \li No constructor, operator=, emplace, and make_optional with std::initializer_list
- *  \li In-place constructor and emplace require copyable arguments,
- *      because boost::in_place requires such
- *  \li Move constructor may or may not exist (it's implicitly defined when available),
- *      because boost::optional lacks a move constructor as of Boost 1.54
- *  \li Non-const operator-> and operator* are not constexpr
- *  \li value() is not constexpr
- *  \li swap is declared without noexcept specification
- *  \li No comparison operators with const T& or nullopt_t
- *  \li No specialized std::hash support
- */
-
-#ifndef NDN_UTIL_BACKPORTS_OPTIONAL_HPP
-#define NDN_UTIL_BACKPORTS_OPTIONAL_HPP
-
-#include "backports.hpp"
-
-#if (__cplusplus > 201402L) && NDN_CXX_HAS_INCLUDE(<optional>)
-#  include <optional>
-#  define NDN_CXX_HAVE_STD_OPTIONAL
-#elif (__cplusplus > 201103L) && NDN_CXX_HAS_INCLUDE(<experimental/optional>)
-#  include <experimental/optional>
-#  if __cpp_lib_experimental_optional >= 201411
-#    define NDN_CXX_HAVE_EXPERIMENTAL_OPTIONAL
-#  endif
-#endif
-
-#if defined(NDN_CXX_HAVE_STD_OPTIONAL)
-
-namespace ndn {
-using std::optional;
-using std::in_place;
-using std::nullopt;
-using std::bad_optional_access;
-using std::make_optional;
-} // namespace ndn
-
-#elif defined(NDN_CXX_HAVE_EXPERIMENTAL_OPTIONAL)
-
-namespace ndn {
-using std::experimental::optional;
-using std::experimental::in_place;
-using std::experimental::nullopt;
-using std::experimental::bad_optional_access;
-using std::experimental::make_optional;
-
-template<typename T, typename... Args>
-constexpr optional<T>
-make_optional(Args&&... args)
-{
-  return optional<T>(in_place, std::forward<Args>(args)...);
-}
-} // namespace ndn
-
-#else
-
-#include <boost/none.hpp>
-#include <boost/optional.hpp>
-#include <boost/utility/typed_in_place_factory.hpp>
-
-namespace ndn {
-
-template<typename T>
-class optional;
-
-struct in_place_t
-{
-};
-constexpr in_place_t in_place{};
-
-class nullopt_t
-{
-public:
-  constexpr explicit
-  nullopt_t(int)
-  {
-  }
-};
-constexpr nullopt_t nullopt{0};
-
-using boost::bad_optional_access;
-
-template<typename T>
-constexpr bool
-operator==(const optional<T>& lhs, const optional<T>& rhs);
-
-template<typename T>
-constexpr bool
-operator!=(const optional<T>& lhs, const optional<T>& rhs);
-
-template<typename T>
-constexpr bool
-operator<(const optional<T>& lhs, const optional<T>& rhs);
-
-template<typename T>
-constexpr bool
-operator<=(const optional<T>& lhs, const optional<T>& rhs);
-
-template<typename T>
-constexpr bool
-operator>(const optional<T>& lhs, const optional<T>& rhs);
-
-template<typename T>
-constexpr bool
-operator>=(const optional<T>& lhs, const optional<T>& rhs);
-
-template<typename T>
-class optional
-{
-public:
-  static_assert(!std::is_same<typename std::remove_cv<T>::type, in_place_t>::value &&
-                !std::is_same<typename std::remove_cv<T>::type, nullopt_t>::value &&
-                !std::is_reference<T>::value,
-                "Invalid instantiation of optional<T>");
-
-  typedef T value_type;
-
-  constexpr
-  optional() noexcept
-  {
-  }
-
-  constexpr
-  optional(nullopt_t) noexcept
-  {
-  }
-
-  constexpr
-  optional(const T& value)
-    : m_boostOptional(value)
-  {
-  }
-
-  template<typename... Args>
-  constexpr explicit
-  optional(in_place_t, Args&&... args)
-    : m_boostOptional(boost::in_place<T>(std::forward<Args>(args)...))
-  {
-  }
-
-  optional&
-  operator=(nullopt_t) noexcept
-  {
-    m_boostOptional = boost::none;
-    return *this;
-  }
-
-  optional&
-  operator=(const optional& other)
-  {
-    m_boostOptional = other.m_boostOptional;
-    return *this;
-  }
-
-  template<typename U,
-           typename = typename std::enable_if<std::is_same<typename std::decay<U>::type, T>::value>::type>
-  optional&
-  operator=(U&& value)
-  {
-    m_boostOptional = std::forward<U>(value);
-    return *this;
-  }
-
-public: // observers
-  constexpr const T*
-  operator->() const
-  {
-    return m_boostOptional.get_ptr();
-  }
-
-  T*
-  operator->()
-  {
-    return m_boostOptional.get_ptr();
-  }
-
-  constexpr const T&
-  operator*() const
-  {
-    return m_boostOptional.get();
-  }
-
-  T&
-  operator*()
-  {
-    return m_boostOptional.get();
-  }
-
-  constexpr explicit
-  operator bool() const noexcept
-  {
-    return static_cast<bool>(m_boostOptional);
-  }
-
-  const T&
-  value() const
-  {
-    return const_cast<optional*>(this)->value();
-  }
-
-  T&
-  value()
-  {
-    return m_boostOptional.value();
-  }
-
-  template<typename U>
-  constexpr T
-  value_or(U&& default_value) const
-  {
-    return m_boostOptional.value_or(default_value);
-  }
-
-public: // modifiers
-  void
-  swap(optional& other)
-  {
-    boost::swap(m_boostOptional, other.m_boostOptional);
-  }
-
-  void
-  reset() noexcept
-  {
-    m_boostOptional = boost::none;
-  }
-
-  template<typename... Args>
-  void
-  emplace(Args&&... args)
-  {
-    m_boostOptional = boost::in_place<T>(std::forward<Args>(args)...);
-  }
-
-private:
-  boost::optional<T> m_boostOptional;
-
-  friend bool operator==<T>(const optional<T>&, const optional<T>&);
-  friend bool operator!=<T>(const optional<T>&, const optional<T>&);
-  friend bool operator< <T>(const optional<T>&, const optional<T>&);
-  friend bool operator<=<T>(const optional<T>&, const optional<T>&);
-  friend bool operator> <T>(const optional<T>&, const optional<T>&);
-  friend bool operator>=<T>(const optional<T>&, const optional<T>&);
-};
-
-template<typename T>
-constexpr bool
-operator==(const optional<T>& lhs, const optional<T>& rhs)
-{
-  return operator==(lhs.m_boostOptional, rhs.m_boostOptional);
-}
-
-template<typename T>
-constexpr bool
-operator!=(const optional<T>& lhs, const optional<T>& rhs)
-{
-  return operator!=(lhs.m_boostOptional, rhs.m_boostOptional);
-}
-
-template<typename T>
-constexpr bool
-operator<(const optional<T>& lhs, const optional<T>& rhs)
-{
-  return operator<(lhs.m_boostOptional, rhs.m_boostOptional);
-}
-
-template<typename T>
-constexpr bool
-operator<=(const optional<T>& lhs, const optional<T>& rhs)
-{
-  return operator<=(lhs.m_boostOptional, rhs.m_boostOptional);
-}
-
-template<typename T>
-constexpr bool
-operator>(const optional<T>& lhs, const optional<T>& rhs)
-{
-  return operator>(lhs.m_boostOptional, rhs.m_boostOptional);
-}
-
-template<typename T>
-constexpr bool
-operator>=(const optional<T>& lhs, const optional<T>& rhs)
-{
-  return operator>=(lhs.m_boostOptional, rhs.m_boostOptional);
-}
-
-template<typename T>
-constexpr optional<typename std::decay<T>::type>
-make_optional(T&& value)
-{
-  return optional<typename std::decay<T>::type>(std::forward<T>(value));
-}
-
-template<typename T, typename... Args>
-constexpr optional<T>
-make_optional(Args&&... args)
-{
-  return optional<T>(in_place, std::forward<Args>(args)...);
-}
-
-} // namespace ndn
-
-#endif
-#endif // NDN_UTIL_BACKPORTS_OPTIONAL_HPP
diff --git a/src/util/backports-ostream-joiner.hpp b/src/util/backports-ostream-joiner.hpp
index 75d53dd..1ba1380 100644
--- a/src/util/backports-ostream-joiner.hpp
+++ b/src/util/backports-ostream-joiner.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2017 Regents of the University of California.
+ * Copyright (c) 2013-2018 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -29,7 +29,7 @@
 
 #include "backports.hpp"
 
-#if (__cplusplus >= 201402L) && NDN_CXX_HAS_INCLUDE(<experimental/iterator>)
+#if NDN_CXX_HAS_INCLUDE(<experimental/iterator>)
 #  include <experimental/iterator>
 #  if __cpp_lib_experimental_ostream_joiner >= 201411
 #    define NDN_CXX_HAVE_EXPERIMENTAL_OSTREAM_JOINER
diff --git a/src/util/backports.hpp b/src/util/backports.hpp
index 18a011ea..70f62f3 100644
--- a/src/util/backports.hpp
+++ b/src/util/backports.hpp
@@ -24,10 +24,6 @@
 
 #include "../common.hpp"
 
-#ifndef NDN_CXX_HAVE_STD_TO_STRING
-#include <boost/lexical_cast.hpp>
-#endif
-
 #ifdef __has_cpp_attribute
 #  define NDN_CXX_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
 #else
@@ -40,40 +36,6 @@
 #  define NDN_CXX_HAS_INCLUDE(x) 0
 #endif
 
-#if (__cplusplus >= 201402L) && NDN_CXX_HAS_CPP_ATTRIBUTE(deprecated)
-#  define NDN_CXX_DEPRECATED_MSG(msg) [[deprecated(msg)]]
-#elif NDN_CXX_HAS_CPP_ATTRIBUTE(gnu::deprecated)
-#  define NDN_CXX_DEPRECATED_MSG(msg) [[gnu::deprecated(msg)]]
-#elif defined(__GNUC__)
-#  define NDN_CXX_DEPRECATED_MSG(msg) __attribute__((deprecated(msg)))
-#else
-#  define NDN_CXX_DEPRECATED_MSG(msg)
-#endif
-
-/** \brief Mark a type, variable, or function as deprecated.
- *
- *  To deprecate a type \c DeprecatedType:
- *  \code
- *  typedef ModernType DeprecatedType NDN_CXX_DEPRECATED;
- *  \endcode
- *  This macro can only be applied to a typedef, not directly on a class.
- *
- *  To deprecate a variable or class member \c deprecatedVar:
- *  \code
- *  int deprecatedVar NDN_CXX_DEPRECATED;
- *  \endcode
- *
- *  To deprecate a function \c deprecatedFunc:
- *  \code
- *  NDN_CXX_DEPRECATED
- *  void
- *  deprecatedFunc(int a, NamedEnum b)
- *  {
- *  }
- *  \endcode
- */
-#define NDN_CXX_DEPRECATED NDN_CXX_DEPRECATED_MSG("")
-
 #if (__cplusplus > 201402L) && NDN_CXX_HAS_CPP_ATTRIBUTE(fallthrough)
 #  define NDN_CXX_FALLTHROUGH [[fallthrough]]
 #elif NDN_CXX_HAS_CPP_ATTRIBUTE(clang::fallthrough)
@@ -86,18 +48,14 @@
 #  define NDN_CXX_FALLTHROUGH ((void)0)
 #endif
 
-namespace ndn {
+#include "backports-ostream-joiner.hpp"
+#include "nonstd/optional.hpp"
 
-#if __cpp_lib_make_unique >= 201304
-using std::make_unique;
-#else
-template<typename T, typename ...Args>
-inline unique_ptr<T>
-make_unique(Args&&... args)
-{
-  return unique_ptr<T>(new T(std::forward<Args>(args)...));
-}
-#endif // __cpp_lib_make_unique
+#ifndef NDN_CXX_HAVE_STD_TO_STRING
+#include <boost/lexical_cast.hpp>
+#endif
+
+namespace ndn {
 
 #ifdef NDN_CXX_HAVE_STD_TO_STRING
 using std::to_string;
@@ -128,9 +86,14 @@
 }
 #endif // __cpp_lib_clamp
 
-} // namespace ndn
+using ::nonstd::optional;
+using ::nonstd::bad_optional_access;
+using ::nonstd::nullopt;
+using ::nonstd::nullopt_t;
+using ::nonstd::in_place;
+using ::nonstd::in_place_t;
+using ::nonstd::make_optional;
 
-#include "backports-optional.hpp"
-#include "backports-ostream-joiner.hpp"
+} // namespace ndn
 
 #endif // NDN_UTIL_BACKPORTS_HPP
diff --git a/src/util/nonstd/optional.hpp b/src/util/nonstd/optional.hpp
new file mode 100644
index 0000000..8a4a31a
--- /dev/null
+++ b/src/util/nonstd/optional.hpp
@@ -0,0 +1,1205 @@
+//
+// Copyright (c) 2014-2017 Martin Moene
+//
+// https://github.com/martinmoene/optional-lite
+//
+// This code is licensed under the MIT License (MIT).
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#pragma once
+
+#ifndef NONSTD_OPTIONAL_LITE_HPP
+#define NONSTD_OPTIONAL_LITE_HPP
+
+#define  optional_lite_VERSION "2.3.2"
+
+// Compiler detection (C++20 is speculative):
+// Note: MSVC supports C++14 since it supports C++17.
+
+#ifdef _MSVC_LANG
+# define optional_MSVC_LANG  _MSVC_LANG
+#else
+# define optional_MSVC_LANG  0
+#endif
+
+#define optional_CPP11             (__cplusplus == 201103L )
+#define optional_CPP11_OR_GREATER  (__cplusplus >= 201103L || optional_MSVC_LANG >= 201103L )
+#define optional_CPP14_OR_GREATER  (__cplusplus >= 201402L || optional_MSVC_LANG >= 201703L )
+#define optional_CPP17_OR_GREATER  (__cplusplus >= 201703L || optional_MSVC_LANG >= 201703L )
+#define optional_CPP20_OR_GREATER  (__cplusplus >= 202000L || optional_MSVC_LANG >= 202000L )
+
+// use C++17 std::optional if available:
+
+#if defined( __has_include )
+# define optional_HAS_INCLUDE( arg )  __has_include( arg )
+#else
+# define optional_HAS_INCLUDE( arg )  0
+#endif
+
+#define optional_HAVE_STD_OPTIONAL  ( optional_CPP17_OR_GREATER && optional_HAS_INCLUDE( <optional> ) )
+
+#if optional_HAVE_STD_OPTIONAL
+
+#include <optional>
+
+namespace nonstd {
+
+    using std::optional;
+    using std::bad_optional_access;
+    using std::hash;
+
+    using std::nullopt;
+    using std::nullopt_t;
+    using std::in_place;
+    using std::in_place_type;
+    using std::in_place_index;
+    using std::in_place_t;
+    using std::in_place_type_t;
+    using std::in_place_index_t;
+
+    using std::operator==;
+    using std::operator!=;
+    using std::operator<;
+    using std::operator<=;
+    using std::operator>;
+    using std::operator>=;
+    using std::make_optional;
+    using std::swap;
+}
+
+#else // C++17 std::optional
+
+#include <cassert>
+#include <stdexcept>
+#include <utility>
+
+// optional-lite alignment configuration:
+
+#ifndef  optional_CONFIG_MAX_ALIGN_HACK
+# define optional_CONFIG_MAX_ALIGN_HACK  0
+#endif
+
+#ifndef  optional_CONFIG_ALIGN_AS
+// no default, used in #if defined()
+#endif
+
+#ifndef  optional_CONFIG_ALIGN_AS_FALLBACK
+# define optional_CONFIG_ALIGN_AS_FALLBACK  double
+#endif
+
+// Compiler warning suppression:
+
+#ifdef __clang__
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wundef"
+#elif defined __GNUC__
+# pragma GCC   diagnostic push
+# pragma GCC   diagnostic ignored "-Wundef"
+#endif
+
+// half-open range [lo..hi):
+#define optional_BETWEEN( v, lo, hi ) ( lo <= v && v < hi )
+
+#if defined(_MSC_VER) && !defined(__clang__)
+# define optional_COMPILER_MSVC_VERSION   (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900)) )
+#else
+# define optional_COMPILER_MSVC_VERSION   0
+#endif
+
+#define optional_COMPILER_VERSION( major, minor, patch )  ( 10 * (10 * major + minor ) + patch )
+
+#if defined __GNUC__
+# define optional_COMPILER_GNUC_VERSION   optional_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
+#else
+# define optional_COMPILER_GNUC_VERSION   0
+#endif
+
+#if defined __clang__
+# define optional_COMPILER_CLANG_VERSION  optional_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
+#else
+# define optional_COMPILER_CLANG_VERSION  0
+#endif
+
+#if optional_BETWEEN(optional_COMPILER_MSVC_VERSION, 70, 140 )
+# pragma warning( push )
+# pragma warning( disable: 4345 )   // initialization behavior changed
+#endif
+
+#if optional_BETWEEN(optional_COMPILER_MSVC_VERSION, 70, 150 )
+# pragma warning( push )
+# pragma warning( disable: 4814 )   // in C++14 'constexpr' will not imply 'const'
+#endif
+
+// Presence of language and library features:
+
+#define optional_HAVE(FEATURE) ( optional_HAVE_##FEATURE )
+
+// Presence of C++11 language features:
+
+#if optional_CPP11_OR_GREATER || optional_COMPILER_MSVC_VERSION >= 100
+# define optional_HAVE_AUTO  1
+# define optional_HAVE_NULLPTR  1
+# define optional_HAVE_STATIC_ASSERT  1
+#endif
+
+#if optional_CPP11_OR_GREATER || optional_COMPILER_MSVC_VERSION >= 120
+# define optional_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG  1
+# define optional_HAVE_INITIALIZER_LIST  1
+#endif
+
+#if optional_CPP11_OR_GREATER || optional_COMPILER_MSVC_VERSION >= 140
+# define optional_HAVE_ALIAS_TEMPLATE  1
+# define optional_HAVE_CONSTEXPR_11  1
+# define optional_HAVE_ENUM_CLASS  1
+# define optional_HAVE_EXPLICIT_CONVERSION  1
+# define optional_HAVE_IS_DEFAULT  1
+# define optional_HAVE_IS_DELETE  1
+# define optional_HAVE_NOEXCEPT  1
+# define optional_HAVE_REF_QUALIFIER  1
+#endif
+
+// Presence of C++14 language features:
+
+#if optional_CPP14_OR_GREATER
+# define optional_HAVE_CONSTEXPR_14  1
+#endif
+
+// Presence of C++17 language features:
+
+#if optional_CPP17_OR_GREATER
+# define optional_HAVE_ENUM_CLASS_CONSTRUCTION_FROM_UNDERLYING_TYPE  1
+#endif
+
+// Presence of C++ library features:
+
+#if optional_COMPILER_GNUC_VERSION
+# define optional_HAVE_TR1_TYPE_TRAITS  1
+# define optional_HAVE_TR1_ADD_POINTER  1
+#endif
+
+#if optional_CPP11_OR_GREATER || optional_COMPILER_MSVC_VERSION >= 90
+# define optional_HAVE_TYPE_TRAITS  1
+# define optional_HAVE_STD_ADD_POINTER  1
+#endif
+
+#if optional_CPP11_OR_GREATER || optional_COMPILER_MSVC_VERSION >= 110
+# define optional_HAVE_ARRAY  1
+#endif
+
+#if optional_CPP11_OR_GREATER || optional_COMPILER_MSVC_VERSION >= 120
+# define optional_HAVE_CONDITIONAL  1
+#endif
+
+#if optional_CPP11_OR_GREATER || optional_COMPILER_MSVC_VERSION >= 140 || (optional_COMPILER_MSVC_VERSION >= 90 && _HAS_CPP0X)
+# define optional_HAVE_CONTAINER_DATA_METHOD  1
+#endif
+
+#if optional_CPP11_OR_GREATER || optional_COMPILER_MSVC_VERSION >= 120
+# define optional_HAVE_REMOVE_CV  1
+#endif
+
+#if optional_CPP11_OR_GREATER || optional_COMPILER_MSVC_VERSION >= 140
+# define optional_HAVE_SIZED_TYPES  1
+#endif
+
+// For the rest, consider VC14 as C++11 for optional-lite:
+
+#if optional_COMPILER_MSVC_VERSION >= 140
+# undef  optional_CPP11_OR_GREATER
+# define optional_CPP11_OR_GREATER  1
+#endif
+
+// C++ feature usage:
+
+#if optional_HAVE( CONSTEXPR_11 )
+# define optional_constexpr  constexpr
+#else
+# define optional_constexpr  /*constexpr*/
+#endif
+
+#if optional_HAVE( CONSTEXPR_14 )
+# define optional_constexpr14  constexpr
+#else
+# define optional_constexpr14  /*constexpr*/
+#endif
+
+#if optional_HAVE( NOEXCEPT )
+# define optional_noexcept  noexcept
+#else
+# define optional_noexcept  /*noexcept*/
+#endif
+
+#if optional_HAVE( NULLPTR )
+# define optional_nullptr  nullptr
+#else
+# define optional_nullptr  NULL
+#endif
+
+#if optional_HAVE( REF_QUALIFIER )
+# define optional_ref_qual  &
+# define optional_refref_qual  &&
+#else
+# define optional_ref_qual  /*&*/
+# define optional_refref_qual  /*&&*/
+#endif
+
+// additional includes:
+
+#if optional_CPP11_OR_GREATER
+# include <functional>
+#endif
+
+#if optional_HAVE( INITIALIZER_LIST )
+# include <initializer_list>
+#endif
+
+#if optional_HAVE( TYPE_TRAITS )
+# include <type_traits>
+#elif optional_HAVE( TR1_TYPE_TRAITS )
+# include <tr1/type_traits>
+#endif
+
+// type traits needed:
+
+namespace nonstd { namespace optional_lite { namespace detail {
+
+#if optional_HAVE( CONDITIONAL )
+    using std::conditional;
+#else
+    template< bool B, typename T, typename F > struct conditional              { typedef T type; };
+    template<         typename T, typename F > struct conditional<false, T, F> { typedef F type; };
+#endif // optional_HAVE_CONDITIONAL
+
+}}}
+
+//
+// in_place: code duplicated in any-lite, optional-lite, variant-lite:
+//
+
+#ifndef nonstd_lite_HAVE_IN_PLACE_TYPES
+
+namespace nonstd {
+
+namespace detail {
+
+template< class T >
+struct in_place_type_tag {};
+
+template< std::size_t I >
+struct in_place_index_tag {};
+
+} // namespace detail
+
+struct in_place_t {};
+
+template< class T >
+inline in_place_t in_place( detail::in_place_type_tag<T> = detail::in_place_type_tag<T>() )
+{
+    return in_place_t();
+}
+
+template< std::size_t I >
+inline in_place_t in_place( detail::in_place_index_tag<I> = detail::in_place_index_tag<I>() )
+{
+    return in_place_t();
+}
+
+template< class T >
+inline in_place_t in_place_type( detail::in_place_type_tag<T> = detail::in_place_type_tag<T>() )
+{
+    return in_place_t();
+}
+
+template< std::size_t I >
+inline in_place_t in_place_index( detail::in_place_index_tag<I> = detail::in_place_index_tag<I>() )
+{
+    return in_place_t();
+}
+
+// mimic templated typedef:
+
+#define nonstd_lite_in_place_type_t( T)  nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T>  )
+#define nonstd_lite_in_place_index_t(T)  nonstd::in_place_t(&)( nonstd::detail::in_place_index_tag<I> )
+
+#define nonstd_lite_HAVE_IN_PLACE_TYPES  1
+
+} // namespace nonstd
+
+#endif // nonstd_lite_HAVE_IN_PLACE_TYPES
+
+//
+// optional:
+//
+
+namespace nonstd { namespace optional_lite {
+
+/// class optional
+
+template< typename T >
+class optional;
+
+namespace detail {
+
+// C++11 emulation:
+
+struct nulltype{};
+
+template< typename Head, typename Tail >
+struct typelist
+{
+    typedef Head head;
+    typedef Tail tail;
+};
+
+#if optional_CONFIG_MAX_ALIGN_HACK
+
+// Max align, use most restricted type for alignment:
+
+#define optional_UNIQUE(  name )       optional_UNIQUE2( name, __LINE__ )
+#define optional_UNIQUE2( name, line ) optional_UNIQUE3( name, line )
+#define optional_UNIQUE3( name, line ) name ## line
+
+#define optional_ALIGN_TYPE( type ) \
+    type optional_UNIQUE( _t ); struct_t< type > optional_UNIQUE( _st )
+
+template< typename T >
+struct struct_t { T _; };
+
+union max_align_t
+{
+    optional_ALIGN_TYPE( char );
+    optional_ALIGN_TYPE( short int );
+    optional_ALIGN_TYPE( int );
+    optional_ALIGN_TYPE( long int  );
+    optional_ALIGN_TYPE( float  );
+    optional_ALIGN_TYPE( double );
+    optional_ALIGN_TYPE( long double );
+    optional_ALIGN_TYPE( char * );
+    optional_ALIGN_TYPE( short int * );
+    optional_ALIGN_TYPE( int *  );
+    optional_ALIGN_TYPE( long int * );
+    optional_ALIGN_TYPE( float * );
+    optional_ALIGN_TYPE( double * );
+    optional_ALIGN_TYPE( long double * );
+    optional_ALIGN_TYPE( void * );
+
+#ifdef HAVE_LONG_LONG
+    optional_ALIGN_TYPE( long long );
+#endif
+
+    struct Unknown;
+
+    Unknown ( * optional_UNIQUE(_) )( Unknown );
+    Unknown * Unknown::* optional_UNIQUE(_);
+    Unknown ( Unknown::* optional_UNIQUE(_) )( Unknown );
+
+    struct_t< Unknown ( * )( Unknown)         > optional_UNIQUE(_);
+    struct_t< Unknown * Unknown::*            > optional_UNIQUE(_);
+    struct_t< Unknown ( Unknown::* )(Unknown) > optional_UNIQUE(_);
+};
+
+#undef optional_UNIQUE
+#undef optional_UNIQUE2
+#undef optional_UNIQUE3
+
+#undef optional_ALIGN_TYPE
+
+#elif defined( optional_CONFIG_ALIGN_AS ) // optional_CONFIG_MAX_ALIGN_HACK
+
+// Use user-specified type for alignment:
+
+#define optional_ALIGN_AS( unused ) \
+    optional_CONFIG_ALIGN_AS
+
+#else // optional_CONFIG_MAX_ALIGN_HACK
+
+// Determine POD type to use for alignment:
+
+#define optional_ALIGN_AS( to_align ) \
+    typename type_of_size< alignment_types, alignment_of< to_align >::value >::type
+
+template <typename T>
+struct alignment_of;
+
+template <typename T>
+struct alignment_of_hack
+{
+    char c;
+    T t;
+    alignment_of_hack();
+};
+
+template <unsigned A, unsigned S>
+struct alignment_logic
+{
+    enum { value = A < S ? A : S };
+};
+
+template< typename T >
+struct alignment_of
+{
+    enum { value = alignment_logic<
+        sizeof( alignment_of_hack<T> ) - sizeof(T), sizeof(T) >::value, };
+};
+
+template< typename List, size_t N >
+struct type_of_size
+{
+    typedef typename conditional<
+        N == sizeof( typename List::head ),
+            typename List::head,
+            typename type_of_size<typename List::tail, N >::type >::type type;
+};
+
+template< size_t N >
+struct type_of_size< nulltype, N >
+{
+    typedef optional_CONFIG_ALIGN_AS_FALLBACK type;
+};
+
+template< typename T>
+struct struct_t { T _; };
+
+#define optional_ALIGN_TYPE( type ) \
+    typelist< type , typelist< struct_t< type >
+
+struct Unknown;
+
+typedef
+    optional_ALIGN_TYPE( char ),
+    optional_ALIGN_TYPE( short ),
+    optional_ALIGN_TYPE( int ),
+    optional_ALIGN_TYPE( long ),
+    optional_ALIGN_TYPE( float ),
+    optional_ALIGN_TYPE( double ),
+    optional_ALIGN_TYPE( long double ),
+
+    optional_ALIGN_TYPE( char *),
+    optional_ALIGN_TYPE( short * ),
+    optional_ALIGN_TYPE( int * ),
+    optional_ALIGN_TYPE( long * ),
+    optional_ALIGN_TYPE( float * ),
+    optional_ALIGN_TYPE( double * ),
+    optional_ALIGN_TYPE( long double * ),
+
+    optional_ALIGN_TYPE( Unknown ( * )( Unknown ) ),
+    optional_ALIGN_TYPE( Unknown * Unknown::*     ),
+    optional_ALIGN_TYPE( Unknown ( Unknown::* )( Unknown ) ),
+
+    nulltype
+    > > > > > > >    > > > > > > >
+    > > > > > > >    > > > > > > >
+    > > > > > >
+    alignment_types;
+
+#undef optional_ALIGN_TYPE
+
+#endif // optional_CONFIG_MAX_ALIGN_HACK
+
+/// C++03 constructed union to hold value.
+
+template< typename T >
+union storage_t
+{
+private:
+    friend class optional<T>;
+
+    typedef T value_type;
+
+    storage_t() {}
+
+    storage_t( value_type const & v )
+    {
+        construct_value( v );
+    }
+
+    void construct_value( value_type const & v )
+    {
+        ::new( value_ptr() ) value_type( v );
+    }
+
+#if optional_CPP11_OR_GREATER
+
+    storage_t( value_type && v )
+    {
+        construct_value( std::move( v ) );
+    }
+
+    void construct_value( value_type && v )
+    {
+        ::new( value_ptr() ) value_type( std::move( v ) );
+    }
+
+#endif
+
+    void destruct_value()
+    {
+        value_ptr()->~T();
+    }
+
+    value_type const * value_ptr() const
+    {
+        return as<value_type>();
+    }
+
+    value_type * value_ptr()
+    {
+        return as<value_type>();
+    }
+
+    value_type const & value() const optional_ref_qual
+    {
+        return * value_ptr();
+    }
+
+    value_type & value() optional_ref_qual
+    {
+        return * value_ptr();
+    }
+
+#if optional_CPP11_OR_GREATER
+
+    value_type const && value() const optional_refref_qual
+    {
+        return * value_ptr();
+    }
+
+    value_type && value() optional_refref_qual
+    {
+        return * value_ptr();
+    }
+
+#endif
+
+#if optional_CPP11_OR_GREATER
+
+    using aligned_storage_t = typename std::aligned_storage< sizeof(value_type), alignof(value_type) >::type;
+    aligned_storage_t data;
+
+#elif optional_CONFIG_MAX_ALIGN_HACK
+
+    typedef struct { unsigned char data[ sizeof(value_type) ]; } aligned_storage_t;
+
+    max_align_t hack;
+    aligned_storage_t data;
+
+#else
+    typedef optional_ALIGN_AS(value_type) align_as_type;
+
+    typedef struct { align_as_type data[ 1 + ( sizeof(value_type) - 1 ) / sizeof(align_as_type) ]; } aligned_storage_t;
+    aligned_storage_t data;
+
+#   undef optional_ALIGN_AS
+
+#endif // optional_CONFIG_MAX_ALIGN_HACK
+
+    void * ptr() optional_noexcept
+    {
+        return &data;
+    }
+
+    void const * ptr() const optional_noexcept
+    {
+        return &data;
+    }
+
+    template <typename U>
+    U * as()
+    {
+        return reinterpret_cast<U*>( ptr() );
+    }
+
+    template <typename U>
+    U const * as() const
+    {
+        return reinterpret_cast<U const *>( ptr() );
+    }
+};
+
+} // namespace detail
+
+/// disengaged state tag
+
+struct nullopt_t
+{
+    struct init{};
+    optional_constexpr nullopt_t( init ) {}
+};
+
+#if optional_HAVE( CONSTEXPR_11 )
+constexpr nullopt_t nullopt{ nullopt_t::init{} };
+#else
+// extra parenthesis to prevent the most vexing parse:
+const nullopt_t nullopt(( nullopt_t::init() ));
+#endif
+
+/// optional access error
+
+class bad_optional_access : public std::logic_error
+{
+public:
+  explicit bad_optional_access()
+  : logic_error( "bad optional access" ) {}
+};
+
+/// optional
+
+template< typename T>
+class optional
+{
+private:
+    typedef void (optional::*safe_bool)() const;
+
+public:
+    typedef T value_type;
+
+    optional_constexpr optional() optional_noexcept
+    : has_value_( false )
+    , contained()
+    {}
+
+    optional_constexpr optional( nullopt_t ) optional_noexcept
+    : has_value_( false )
+    , contained()
+    {}
+
+    optional( optional const & rhs )
+    : has_value_( rhs.has_value() )
+    {
+        if ( rhs.has_value() )
+            contained.construct_value( rhs.contained.value() );
+    }
+
+#if optional_CPP11_OR_GREATER
+    optional_constexpr14 optional( optional && rhs ) noexcept( std::is_nothrow_move_constructible<T>::value )
+    : has_value_( rhs.has_value() )
+    {
+        if ( rhs.has_value() )
+            contained.construct_value( std::move( rhs.contained.value() ) );
+    }
+#endif
+
+    optional_constexpr optional( value_type const & value )
+    : has_value_( true )
+    , contained( value )
+    {}
+
+#if optional_CPP11_OR_GREATER
+
+    optional_constexpr optional( value_type && value )
+    : has_value_( true )
+    , contained( std::move( value ) )
+    {}
+
+    template< class... Args >
+    optional_constexpr explicit optional( nonstd_lite_in_place_type_t(T), Args&&... args )
+    : has_value_( true )
+    , contained( T( std::forward<Args>(args)...) )
+    {}
+
+    template< class U, class... Args >
+    optional_constexpr explicit optional( nonstd_lite_in_place_type_t(T), std::initializer_list<U> il, Args&&... args )
+    : has_value_( true )
+    , contained( T( il, std::forward<Args>(args)...) )
+    {}
+
+#endif // optional_CPP11_OR_GREATER
+
+    ~optional()
+    {
+        if ( has_value() )
+            contained.destruct_value();
+    }
+
+    // assignment
+
+    optional & operator=( nullopt_t ) optional_noexcept
+    {
+        reset();
+        return *this;
+    }
+
+    optional & operator=( optional const & rhs )
+#if optional_CPP11_OR_GREATER
+        noexcept( std::is_nothrow_move_assignable<T>::value && std::is_nothrow_move_constructible<T>::value )
+#endif
+    {
+        if      ( has_value() == true  && rhs.has_value() == false ) reset();
+        else if ( has_value() == false && rhs.has_value() == true  ) initialize( *rhs );
+        else if ( has_value() == true  && rhs.has_value() == true  ) contained.value() = *rhs;
+        return *this;
+    }
+
+#if optional_CPP11_OR_GREATER
+
+    optional & operator=( optional && rhs ) noexcept
+    {
+        if      ( has_value() == true  && rhs.has_value() == false ) reset();
+        else if ( has_value() == false && rhs.has_value() == true  ) initialize( std::move( *rhs ) );
+        else if ( has_value() == true  && rhs.has_value() == true  ) contained.value() = std::move( *rhs );
+        return *this;
+    }
+
+    template< class U,
+        typename = typename std::enable_if< std::is_same< typename std::decay<U>::type, T>::value >::type >
+    optional & operator=( U && v )
+    {
+        if ( has_value() ) contained.value() = std::forward<U>( v );
+        else               initialize( T( std::forward<U>( v ) ) );
+        return *this;
+    }
+
+    template< class... Args >
+    void emplace( Args&&... args )
+    {
+        *this = nullopt;
+        initialize( T( std::forward<Args>(args)...) );
+    }
+
+    template< class U, class... Args >
+    void emplace( std::initializer_list<U> il, Args&&... args )
+    {
+        *this = nullopt;
+        initialize( T( il, std::forward<Args>(args)...) );
+    }
+
+#endif // optional_CPP11_OR_GREATER
+
+    // swap
+
+    void swap( optional & rhs )
+#if optional_CPP11_OR_GREATER
+    noexcept( std::is_nothrow_move_constructible<T>::value && noexcept( std::swap( std::declval<T&>(), std::declval<T&>() ) ) )
+#endif
+    {
+        using std::swap;
+        if      ( has_value() == true  && rhs.has_value() == true  ) { swap( **this, *rhs ); }
+        else if ( has_value() == false && rhs.has_value() == true  ) { initialize( *rhs ); rhs.reset(); }
+        else if ( has_value() == true  && rhs.has_value() == false ) { rhs.initialize( **this ); reset(); }
+    }
+
+    // observers
+
+    optional_constexpr value_type const * operator ->() const
+    {
+        return assert( has_value() ),
+            contained.value_ptr();
+    }
+
+    optional_constexpr14 value_type * operator ->()
+    {
+        return assert( has_value() ),
+            contained.value_ptr();
+    }
+
+    optional_constexpr value_type const & operator *() const optional_ref_qual
+    {
+        return assert( has_value() ),
+            contained.value();
+    }
+
+    optional_constexpr14 value_type & operator *() optional_ref_qual
+    {
+        return assert( has_value() ),
+            contained.value();
+    }
+
+#if optional_CPP11_OR_GREATER
+
+    optional_constexpr value_type const && operator *() const optional_refref_qual
+    {
+        return assert( has_value() ),
+            std::move( contained.value() );
+    }
+
+    optional_constexpr14 value_type && operator *() optional_refref_qual
+    {
+        return assert( has_value() ),
+            std::move( contained.value() );
+    }
+
+#endif
+
+#if optional_CPP11_OR_GREATER
+    optional_constexpr explicit operator bool() const optional_noexcept
+    {
+        return has_value();
+    }
+#else
+    optional_constexpr operator safe_bool() const optional_noexcept
+    {
+        return has_value() ? &optional::this_type_does_not_support_comparisons : 0;
+    }
+#endif
+
+    optional_constexpr bool has_value() const optional_noexcept
+    {
+        return has_value_;
+    }
+
+    optional_constexpr14 value_type const & value() const optional_ref_qual
+    {
+        if ( ! has_value() )
+            throw bad_optional_access();
+
+        return contained.value();
+    }
+
+    optional_constexpr14 value_type & value() optional_ref_qual
+    {
+        if ( ! has_value() )
+            throw bad_optional_access();
+
+        return contained.value();
+    }
+
+#if optional_HAVE( REF_QUALIFIER )
+
+    optional_constexpr14 value_type const && value() const optional_refref_qual
+    {
+        if ( ! has_value() )
+            throw bad_optional_access();
+
+        return std::move( contained.value() );
+    }
+
+    optional_constexpr14 value_type && value() optional_refref_qual
+    {
+        if ( ! has_value() )
+            throw bad_optional_access();
+
+        return std::move( contained.value() );
+    }
+
+#endif
+
+#if optional_CPP11_OR_GREATER
+
+    template< class U >
+    optional_constexpr value_type value_or( U && v ) const optional_ref_qual
+    {
+        return has_value() ? contained.value() : static_cast<T>(std::forward<U>( v ) );
+    }
+
+    template< class U >
+    optional_constexpr value_type value_or( U && v ) const optional_refref_qual
+    {
+        return has_value() ? std::move( contained.value() ) : static_cast<T>(std::forward<U>( v ) );
+    }
+
+#else
+
+    template< class U >
+    optional_constexpr value_type value_or( U const & v ) const
+    {
+        return has_value() ? contained.value() : static_cast<value_type>( v );
+    }
+
+#endif // optional_CPP11_OR_GREATER
+
+    // modifiers
+
+    void reset() optional_noexcept
+    {
+        if ( has_value() )
+            contained.destruct_value();
+
+        has_value_ = false;
+    }
+
+private:
+    void this_type_does_not_support_comparisons() const {}
+
+    template< typename V >
+    void initialize( V const & value )
+    {
+        assert( ! has_value()  );
+        contained.construct_value( value );
+        has_value_ = true;
+    }
+
+#if optional_CPP11_OR_GREATER
+    template< typename V >
+    void initialize( V && value )
+    {
+        assert( ! has_value()  );
+        contained.construct_value( std::move( value ) );
+        has_value_ = true;
+    }
+#endif
+
+private:
+    bool has_value_;
+    detail::storage_t< value_type > contained;
+
+};
+
+// Relational operators
+
+template< typename T, typename U >
+inline optional_constexpr bool operator==( optional<T> const & x, optional<U> const & y )
+{
+    return bool(x) != bool(y) ? false : !bool( x ) ? true : *x == *y;
+}
+
+template< typename T, typename U >
+inline optional_constexpr bool operator!=( optional<T> const & x, optional<U> const & y )
+{
+    return !(x == y);
+}
+
+template< typename T, typename U >
+inline optional_constexpr bool operator<( optional<T> const & x, optional<U> const & y )
+{
+    return (!y) ? false : (!x) ? true : *x < *y;
+}
+
+template< typename T, typename U >
+inline optional_constexpr bool operator>( optional<T> const & x, optional<U> const & y )
+{
+    return (y < x);
+}
+
+template< typename T, typename U >
+inline optional_constexpr bool operator<=( optional<T> const & x, optional<U> const & y )
+{
+    return !(y < x);
+}
+
+template< typename T, typename U >
+inline optional_constexpr bool operator>=( optional<T> const & x, optional<U> const & y )
+{
+    return !(x < y);
+}
+
+// Comparison with nullopt
+
+template< typename T >
+inline optional_constexpr bool operator==( optional<T> const & x, nullopt_t ) optional_noexcept
+{
+    return (!x);
+}
+
+template< typename T >
+inline optional_constexpr bool operator==( nullopt_t, optional<T> const & x ) optional_noexcept
+{
+    return (!x);
+}
+
+template< typename T >
+inline optional_constexpr bool operator!=( optional<T> const & x, nullopt_t ) optional_noexcept
+{
+    return bool(x);
+}
+
+template< typename T >
+inline optional_constexpr bool operator!=( nullopt_t, optional<T> const & x ) optional_noexcept
+{
+    return bool(x);
+}
+
+template< typename T >
+inline optional_constexpr bool operator<( optional<T> const &, nullopt_t ) optional_noexcept
+{
+    return false;
+}
+
+template< typename T >
+inline optional_constexpr bool operator<( nullopt_t, optional<T> const & x ) optional_noexcept
+{
+    return bool(x);
+}
+
+template< typename T >
+inline optional_constexpr bool operator<=( optional<T> const & x, nullopt_t ) optional_noexcept
+{
+    return (!x);
+}
+
+template< typename T >
+inline optional_constexpr bool operator<=( nullopt_t, optional<T> const & ) optional_noexcept
+{
+    return true;
+}
+
+template< typename T >
+inline optional_constexpr bool operator>( optional<T> const & x, nullopt_t ) optional_noexcept
+{
+    return bool(x);
+}
+
+template< typename T >
+inline optional_constexpr bool operator>( nullopt_t, optional<T> const & ) optional_noexcept
+{
+    return false;
+}
+
+template< typename T >
+inline optional_constexpr bool operator>=( optional<T> const &, nullopt_t ) optional_noexcept
+{
+    return true;
+}
+
+template< typename T >
+inline optional_constexpr bool operator>=( nullopt_t, optional<T> const & x ) optional_noexcept
+{
+    return (!x);
+}
+
+// Comparison with T
+
+template< typename T, typename U >
+inline optional_constexpr bool operator==( optional<T> const & x, U const & v )
+{
+    return bool(x) ? *x == v : false;
+}
+
+template< typename T, typename U >
+inline optional_constexpr bool operator==( U const & v, optional<T> const & x )
+{
+    return bool(x) ? v == *x : false;
+}
+
+template< typename T, typename U >
+inline optional_constexpr bool operator!=( optional<T> const & x, U const & v )
+{
+    return bool(x) ? *x != v : true;
+}
+
+template< typename T, typename U >
+inline optional_constexpr bool operator!=( U const & v, optional<T> const & x )
+{
+    return bool(x) ? v != *x : true;
+}
+
+template< typename T, typename U >
+inline optional_constexpr bool operator<( optional<T> const & x, U const & v )
+{
+    return bool(x) ? *x < v : true;
+}
+
+template< typename T, typename U >
+inline optional_constexpr bool operator<( U const & v, optional<T> const & x )
+{
+    return bool(x) ? v < *x : false;
+}
+
+template< typename T, typename U >
+inline optional_constexpr bool operator<=( optional<T> const & x, U const & v )
+{
+    return bool(x) ? *x <= v : true;
+}
+
+template< typename T, typename U >
+inline optional_constexpr bool operator<=( U const & v, optional<T> const & x )
+{
+    return bool(x) ? v <= *x : false;
+}
+
+template< typename T, typename U >
+inline optional_constexpr bool operator>( optional<T> const & x, U const & v )
+{
+    return bool(x) ? *x > v : false;
+}
+
+template< typename T, typename U >
+inline optional_constexpr bool operator>( U const & v, optional<T> const & x )
+{
+    return bool(x) ? v > *x : true;
+}
+
+template< typename T, typename U >
+inline optional_constexpr bool operator>=( optional<T> const & x, U const & v )
+{
+    return bool(x) ? *x >= v : false;
+}
+
+template< typename T, typename U >
+inline optional_constexpr bool operator>=( U const & v, optional<T> const & x )
+{
+    return bool(x) ? v >= *x : true;
+}
+
+// Specialized algorithms
+
+template< typename T >
+void swap( optional<T> & x, optional<T> & y )
+#if optional_CPP11_OR_GREATER
+    noexcept( noexcept( x.swap(y) ) )
+#endif
+{
+    x.swap( y );
+}
+
+#if optional_CPP11_OR_GREATER
+
+template< class T >
+optional_constexpr optional< typename std::decay<T>::type > make_optional( T && v )
+{
+    return optional< typename std::decay<T>::type >( std::forward<T>( v ) );
+}
+
+template< class T, class...Args >
+optional_constexpr optional<T> make_optional( Args&&... args )
+{
+    return optional<T>( in_place, std::forward<Args>(args)...);
+}
+
+template< class T, class U, class... Args >
+optional_constexpr optional<T> make_optional( std::initializer_list<U> il, Args&&... args )
+{
+    return optional<T>( in_place, il, std::forward<Args>(args)...);
+}
+
+#else
+
+template< typename T >
+optional<T> make_optional( T const & v )
+{
+    return optional<T>( v );
+}
+
+#endif // optional_CPP11_OR_GREATER
+
+} // namespace optional
+
+using namespace optional_lite;
+
+} // namespace nonstd
+
+#if optional_CPP11_OR_GREATER
+
+// specialize the std::hash algorithm:
+
+namespace std {
+
+template< class T >
+struct hash< nonstd::optional<T> >
+{
+public:
+    std::size_t operator()( nonstd::optional<T> const & v ) const optional_noexcept
+    {
+        return bool( v ) ? hash<T>()( *v ) : 0;
+    }
+};
+
+} //namespace std
+
+#endif // optional_CPP11_OR_GREATER
+
+#ifdef __clang__
+# pragma clang diagnostic pop
+#elif defined __GNUC__
+# pragma GCC   diagnostic pop
+#endif
+
+#endif // have C++17 std::optional
+
+#endif // NONSTD_OPTIONAL_LITE_HPP
diff --git a/src/util/segment-fetcher.hpp b/src/util/segment-fetcher.hpp
index 13fbd3d..3b81cb4 100644
--- a/src/util/segment-fetcher.hpp
+++ b/src/util/segment-fetcher.hpp
@@ -162,7 +162,7 @@
    * @param errorCallback       Callback to be fired when an error occurs (@see Errors)
    * @return A shared_ptr to the constructed SegmentFetcher
    */
-  NDN_CXX_DEPRECATED_MSG("Use SegmentFetcher::start instead")
+  [[deprecated("use SegmentFetcher::start instead")]]
   static
   shared_ptr<SegmentFetcher>
   fetch(Face& face,
@@ -189,7 +189,7 @@
    * @param errorCallback       Callback to be fired when an error occurs (@see Errors)
    * @return A shared_ptr to the constructed SegmentFetcher
    */
-  NDN_CXX_DEPRECATED_MSG("Use SegmentFetcher::start instead")
+  [[deprecated("use SegmentFetcher::start instead")]]
   static
   shared_ptr<SegmentFetcher>
   fetch(Face& face,