util: backport C++17 std::any and std::variant

The backported implementations are taken from Martin Moene's any-lite
(commit a2ee2e1cc4a3fcfe42ab44c46a65467b76b58f25) and variant-lite
(commit ff251b02253ff28db49bb20a79200514d8267d87).

The bundled copy of optional-lite is updated to commit
9a370efe62e084729a171a407b017aa58dc954c1.

Change-Id: I4afe117e357c82d51002f96b083aed0ec5eeda35
diff --git a/src/util/nonstd/any.hpp b/src/util/nonstd/any.hpp
new file mode 100644
index 0000000..7c02c63
--- /dev/null
+++ b/src/util/nonstd/any.hpp
@@ -0,0 +1,643 @@
+//
+// Copyright (c) 2016-2018 Martin Moene
+//
+// https://github.com/martinmoene/any-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)
+
+#pragma once
+
+#ifndef NONSTD_ANY_LITE_HPP
+#define NONSTD_ANY_LITE_HPP
+
+#define any_lite_MAJOR  0
+#define any_lite_MINOR  1
+#define any_lite_PATCH  0
+
+#define any_lite_VERSION  any_STRINGIFY(any_lite_MAJOR) "." any_STRINGIFY(any_lite_MINOR) "." any_STRINGIFY(any_lite_PATCH)
+
+#define any_STRINGIFY(  x )  any_STRINGIFY_( x )
+#define any_STRINGIFY_( x )  #x
+
+// any-lite configuration:
+
+#define any_ANY_DEFAULT  0
+#define any_ANY_NONSTD   1
+#define any_ANY_STD      2
+
+#if !defined( any_CONFIG_SELECT_ANY )
+# define any_CONFIG_SELECT_ANY  ( any_HAVE_STD_ANY ? any_ANY_STD : any_ANY_NONSTD )
+#endif
+
+// C++ language version detection (C++20 is speculative):
+// Note: VC14.0/1900 (VS2015) lacks too much from C++14.
+
+#ifndef   any_CPLUSPLUS
+# if defined(_MSVC_LANG ) && !defined(__clang__)
+#  define any_CPLUSPLUS  (_MSC_VER == 1900 ? 201103L : _MSVC_LANG )
+# else
+#  define any_CPLUSPLUS  __cplusplus
+# endif
+#endif
+
+#define any_CPP98_OR_GREATER  ( any_CPLUSPLUS >= 199711L )
+#define any_CPP11_OR_GREATER  ( any_CPLUSPLUS >= 201103L )
+#define any_CPP14_OR_GREATER  ( any_CPLUSPLUS >= 201402L )
+#define any_CPP17_OR_GREATER  ( any_CPLUSPLUS >= 201703L )
+#define any_CPP20_OR_GREATER  ( any_CPLUSPLUS >= 202000L )
+
+// Use C++17 std::any if available and requested:
+
+#if any_CPP17_OR_GREATER && defined(__has_include )
+# if __has_include( <any> )
+#  define any_HAVE_STD_ANY  1
+# else
+#  define any_HAVE_STD_ANY  0
+# endif
+#else
+# define  any_HAVE_STD_ANY  0
+#endif
+
+#define  any_USES_STD_ANY  ( (any_CONFIG_SELECT_ANY == any_ANY_STD) || ((any_CONFIG_SELECT_ANY == any_ANY_DEFAULT) && any_HAVE_STD_ANY) )
+
+//
+// in_place: code duplicated in any-lite, expected-lite, optional-lite, value-ptr-lite, variant-lite:
+//
+
+#ifndef nonstd_lite_HAVE_IN_PLACE_TYPES
+#define nonstd_lite_HAVE_IN_PLACE_TYPES  1
+
+// C++17 std::in_place in <utility>:
+
+#if any_CPP17_OR_GREATER
+
+#include <utility>
+
+namespace nonstd {
+
+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;
+
+#define nonstd_lite_in_place_t(      T)  std::in_place_t
+#define nonstd_lite_in_place_type_t( T)  std::in_place_type_t<T>
+#define nonstd_lite_in_place_index_t(K)  std::in_place_index_t<K>
+
+#define nonstd_lite_in_place(      T)    std::in_place_t{}
+#define nonstd_lite_in_place_type( T)    std::in_place_type_t<T>{}
+#define nonstd_lite_in_place_index(K)    std::in_place_index_t<K>{}
+
+} // namespace nonstd
+
+#else // any_CPP17_OR_GREATER
+
+#include <cstddef>
+
+namespace nonstd {
+namespace detail {
+
+template< class T >
+struct in_place_type_tag {};
+
+template< std::size_t K >
+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 K >
+inline in_place_t in_place( detail::in_place_index_tag<K> = detail::in_place_index_tag<K>() )
+{
+    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 K >
+inline in_place_t in_place_index( detail::in_place_index_tag<K> = detail::in_place_index_tag<K>() )
+{
+    return in_place_t();
+}
+
+// mimic templated typedef:
+
+#define nonstd_lite_in_place_t(      T)  nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T>  )
+#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(K)  nonstd::in_place_t(&)( nonstd::detail::in_place_index_tag<K> )
+
+#define nonstd_lite_in_place(      T)    nonstd::in_place_type<T>
+#define nonstd_lite_in_place_type( T)    nonstd::in_place_type<T>
+#define nonstd_lite_in_place_index(K)    nonstd::in_place_index<K>
+
+} // namespace nonstd
+
+#endif // any_CPP17_OR_GREATER
+#endif // nonstd_lite_HAVE_IN_PLACE_TYPES
+
+//
+// Using std::any:
+//
+
+#if any_USES_STD_ANY
+
+#include <any>
+#include <utility>
+
+namespace nonstd {
+
+    using std::any;
+    using std::any_cast;
+    using std::make_any;
+    using std::swap;
+    using std::bad_any_cast;
+}
+
+#else // any_USES_STD_ANY
+
+#include <typeinfo>
+#include <utility>
+
+// Compiler versions:
+//
+// MSVC++ 6.0  _MSC_VER == 1200 (Visual Studio 6.0)
+// MSVC++ 7.0  _MSC_VER == 1300 (Visual Studio .NET 2002)
+// MSVC++ 7.1  _MSC_VER == 1310 (Visual Studio .NET 2003)
+// MSVC++ 8.0  _MSC_VER == 1400 (Visual Studio 2005)
+// MSVC++ 9.0  _MSC_VER == 1500 (Visual Studio 2008)
+// MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010)
+// MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012)
+// MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013)
+// MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015)
+// MSVC++ 14.1 _MSC_VER >= 1910 (Visual Studio 2017)
+
+#if defined(_MSC_VER ) && !defined(__clang__)
+# define any_COMPILER_MSVC_VER      (_MSC_VER )
+# define any_COMPILER_MSVC_VERSION  (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) )
+#else
+# define any_COMPILER_MSVC_VER      0
+# define any_COMPILER_MSVC_VERSION  0
+#endif
+
+#define any_COMPILER_VERSION( major, minor, patch )  ( 10 * ( 10 * (major) + (minor) ) + (patch) )
+
+#if defined(__clang__)
+# define any_COMPILER_CLANG_VERSION  any_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
+#else
+# define any_COMPILER_CLANG_VERSION  0
+#endif
+
+#if defined(__GNUC__) && !defined(__clang__)
+# define any_COMPILER_GNUC_VERSION  any_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
+#else
+# define any_COMPILER_GNUC_VERSION  0
+#endif
+
+// half-open range [lo..hi):
+//#define any_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) )
+
+// Presence of language and library features:
+
+#define any_HAVE( feature )  ( any_HAVE_##feature )
+
+#ifdef _HAS_CPP0X
+# define any_HAS_CPP0X  _HAS_CPP0X
+#else
+# define any_HAS_CPP0X  0
+#endif
+
+#define any_CPP11_90   (any_CPP11_OR_GREATER || any_COMPILER_MSVC_VER >= 1500)
+#define any_CPP11_100  (any_CPP11_OR_GREATER || any_COMPILER_MSVC_VER >= 1600)
+#define any_CPP11_120  (any_CPP11_OR_GREATER || any_COMPILER_MSVC_VER >= 1800)
+#define any_CPP11_140  (any_CPP11_OR_GREATER || any_COMPILER_MSVC_VER >= 1900)
+
+#define any_CPP14_000  (any_CPP14_OR_GREATER)
+#define any_CPP17_000  (any_CPP17_OR_GREATER)
+
+// Presence of C++11 language features:
+
+#define any_HAVE_CONSTEXPR_11           any_CPP11_140
+#define any_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG \
+                                        any_CPP11_120
+#define any_HAVE_INITIALIZER_LIST       any_CPP11_120
+#define any_HAVE_NOEXCEPT               any_CPP11_140
+#define any_HAVE_NULLPTR                any_CPP11_100
+#define any_HAVE_TYPE_TRAITS            any_CPP11_90
+#define any_HAVE_STATIC_ASSERT          any_CPP11_100
+#define any_HAVE_ADD_CONST              any_CPP11_90
+#define any_HAVE_REMOVE_REFERENCE       any_CPP11_90
+
+#define any_HAVE_TR1_ADD_CONST          (!! any_COMPILER_GNUC_VERSION )
+#define any_HAVE_TR1_REMOVE_REFERENCE   (!! any_COMPILER_GNUC_VERSION )
+#define any_HAVE_TR1_TYPE_TRAITS        (!! any_COMPILER_GNUC_VERSION )
+
+// Presence of C++14 language features:
+
+#define any_HAVE_CONSTEXPR_14           any_CPP14_000
+
+// Presence of C++17 language features:
+
+#define any_HAVE_NODISCARD              any_CPP17_000
+
+// Presence of C++ library features:
+
+#if any_HAVE_CONSTEXPR_11
+# define any_constexpr constexpr
+#else
+# define any_constexpr /*constexpr*/
+#endif
+
+#if any_HAVE_CONSTEXPR_14
+# define any_constexpr14 constexpr
+#else
+# define any_constexpr14 /*constexpr*/
+#endif
+
+#if any_HAVE_NOEXCEPT
+# define any_noexcept noexcept
+#else
+# define any_noexcept /*noexcept*/
+#endif
+
+#if any_HAVE_NULLPTR
+# define any_nullptr nullptr
+#else
+# define any_nullptr NULL
+#endif
+
+#if any_HAVE_NODISCARD
+# define any_nodiscard [[nodiscard]]
+#else
+# define any_nodiscard /*[[nodiscard]]*/
+#endif
+
+// additional includes:
+
+#if ! any_HAVE_NULLPTR
+# include <cstddef>
+#endif
+
+#if any_HAVE_INITIALIZER_LIST
+# include <initializer_list>
+#endif
+
+#if any_HAVE_TYPE_TRAITS
+# include <type_traits>
+#elif any_HAVE_TR1_TYPE_TRAITS
+# include <tr1/type_traits>
+#endif
+
+//
+// any:
+//
+
+namespace nonstd {  namespace any_lite {
+
+namespace detail {
+
+// C++11 emulation:
+
+#if any_HAVE_ADD_CONST
+
+using std::add_const;
+
+#elif any_HAVE_TR1_ADD_CONST
+
+using std::tr1::add_const;
+
+#else
+
+template< class T > struct add_const { typedef const T type; };
+
+#endif // any_HAVE_ADD_CONST
+
+#if any_HAVE_REMOVE_REFERENCE
+
+using std::remove_reference;
+
+#elif any_HAVE_TR1_REMOVE_REFERENCE
+
+using std::tr1::remove_reference;
+
+#else
+
+template< class T > struct remove_reference     { typedef T type; };
+template< class T > struct remove_reference<T&> { typedef T type; };
+
+#endif // any_HAVE_REMOVE_REFERENCE
+
+} // namespace detail
+
+class bad_any_cast : public std::bad_cast
+{
+public:
+#if any_CPP11_OR_GREATER
+    virtual const char* what() const any_noexcept
+#else
+    virtual const char* what() const throw()
+#endif
+   {
+      return "any-lite: bad any_cast";
+   }
+};
+
+class any
+{
+public:
+    any_constexpr any() any_noexcept
+    : content( any_nullptr )
+    {}
+
+    any( any const & other )
+    : content( other.content ? other.content->clone() : any_nullptr )
+    {}
+
+#if any_CPP11_OR_GREATER
+
+    any( any && other ) any_noexcept
+    : content( std::move( other.content ) )
+    {
+        other.content = any_nullptr;
+    }
+
+    template<
+        class ValueType, class T = typename std::decay<ValueType>::type
+        , typename = typename std::enable_if< ! std::is_same<T, any>::value >::type
+    >
+    any( ValueType && value ) any_noexcept
+    : content( new holder<T>( std::move( value ) ) )
+    {}
+
+    template<
+        class T, class... Args
+        , typename = typename std::enable_if< std::is_constructible<T, Args...>::value >::type
+    >
+    explicit any( nonstd_lite_in_place_type_t(T), Args&&... args )
+    : content( new holder<T>( T( std::forward<Args>(args)... ) ) )
+    {}
+
+    template<
+        class T, class U, class... Args
+        , typename = typename std::enable_if< std::is_constructible<T, std::initializer_list<U>&, Args...>::value >::type
+    >
+    explicit any( nonstd_lite_in_place_type_t(T), std::initializer_list<U> il, Args&&... args )
+    : content( new holder<T>( T( il, std::forward<Args>(args)... ) ) )
+    {}
+
+#else
+
+    template< class ValueType >
+    any( ValueType const & value )
+    : content( new holder<ValueType>( value ) )
+    {}
+
+#endif // any_CPP11_OR_GREATER
+
+    ~any()
+    {
+        reset();
+    }
+
+    any & operator=( any const & other )
+    {
+        any( other ).swap( *this );
+        return *this;
+    }
+
+#if any_CPP11_OR_GREATER
+
+    any & operator=( any && other ) any_noexcept
+    {
+        any( std::move( other ) ).swap( *this );
+        return *this;
+    }
+
+    template<
+        class ValueType, class T = typename std::decay<ValueType>::type
+        , typename = typename std::enable_if< ! std::is_same<T, any>::value >::type
+    >
+    any & operator=( ValueType && value )
+    {
+        any( std::move( value ) ).swap( *this );
+        return *this;
+    }
+
+    template< class T, class... Args >
+    void emplace( Args && ... args )
+    {
+        any( T( std::forward<Args>(args)... ) ).swap( *this );
+    }
+
+    template<
+        class T, class U, class... Args
+        , typename = typename std::enable_if< std::is_constructible<T, std::initializer_list<U>&, Args...>::value >::type
+    >
+    void emplace( std::initializer_list<U> il, Args&&... args )
+    {
+        any( T( il, std::forward<Args>(args)... ) ).swap( *this );
+    }
+
+#else
+
+    template< class ValueType >
+    any & operator=( ValueType const & value )
+    {
+        any( value ).swap( *this );
+        return *this;
+    }
+
+#endif // any_CPP11_OR_GREATER
+
+    void reset() any_noexcept
+    {
+        delete content; content = any_nullptr;
+    }
+
+    void swap( any & other ) any_noexcept
+    {
+        std::swap( content, other.content );
+    }
+
+    bool has_value() const any_noexcept
+    {
+        return content != any_nullptr;
+    }
+
+    const std::type_info & type() const any_noexcept
+    {
+        return has_value() ? content->type() : typeid( void );
+    }
+
+    //
+    // non-standard:
+    //
+
+    template< class ValueType >
+    const ValueType * to_ptr() const
+    {
+        return &( static_cast<holder<ValueType> *>( content )->held );
+    }
+
+    template< class ValueType >
+    ValueType * to_ptr()
+    {
+        return &( static_cast<holder<ValueType> *>( content )->held );
+    }
+
+private:
+    class placeholder
+    {
+    public:
+        virtual ~placeholder()
+        {
+        }
+
+        virtual std::type_info const & type() const = 0;
+
+        virtual placeholder * clone() const = 0;
+    };
+
+    template< typename ValueType >
+    class holder : public placeholder
+    {
+    public:
+        holder( ValueType const & value )
+        : held( value )
+        {}
+
+#if any_CPP11_OR_GREATER
+        holder( ValueType && value )
+        : held( std::move( value ) )
+        {}
+#endif
+
+        virtual std::type_info const & type() const
+        {
+            return typeid( ValueType );
+        }
+
+        virtual placeholder * clone() const
+        {
+            return new holder( held );
+        }
+
+        ValueType held;
+    };
+
+    placeholder * content;
+};
+
+inline void swap( any & x, any & y ) any_noexcept
+{
+    x.swap( y );
+}
+
+#if any_CPP11_OR_GREATER
+
+template< class T, class ...Args >
+inline any make_any( Args&& ...args )
+{
+    return any( nonstd_lite_in_place_type(T), std::forward<Args>(args)...);
+}
+
+template< class T, class U, class ...Args >
+inline any make_any( std::initializer_list<U> il, Args&& ...args )
+{
+    return any( nonstd_lite_in_place_type(T), il, std::forward<Args>(args)...);
+}
+
+#endif // any_CPP11_OR_GREATER
+
+template<
+    class ValueType
+#if any_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG
+    , typename = typename std::enable_if< std::is_reference<ValueType>::value || std::is_copy_constructible<ValueType>::value >::type
+#endif
+>
+any_nodiscard inline ValueType any_cast( any const & operand )
+{
+   const ValueType * result = any_cast< typename detail::add_const< typename detail::remove_reference<ValueType>::type >::type >( &operand );
+
+   if ( ! result )
+   {
+      throw bad_any_cast();
+   }
+
+   return *result;
+}
+
+template<
+    class ValueType
+#if any_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG
+    , typename = typename std::enable_if< std::is_reference<ValueType>::value || std::is_copy_constructible<ValueType>::value >::type
+#endif
+>
+any_nodiscard inline ValueType any_cast( any & operand )
+{
+   const ValueType * result = any_cast< typename detail::remove_reference<ValueType>::type >( &operand );
+
+   if ( ! result )
+   {
+      throw bad_any_cast();
+   }
+
+   return *result;
+}
+
+#if any_CPP11_OR_GREATER
+
+template<
+    class ValueType
+#if any_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG
+    , typename = typename std::enable_if< std::is_reference<ValueType>::value || std::is_copy_constructible<ValueType>::value >::type
+#endif
+>
+any_nodiscard inline ValueType any_cast( any && operand )
+{
+   const ValueType * result = any_cast< typename detail::remove_reference<ValueType>::type >( &operand );
+
+   if ( ! result )
+   {
+      throw bad_any_cast();
+   }
+
+   return *result;
+}
+
+#endif // any_CPP11_OR_GREATER
+
+template< class ValueType >
+any_nodiscard inline ValueType const * any_cast( any const * operand ) any_noexcept
+{
+    return operand != any_nullptr && operand->type() == typeid(ValueType) ? operand->to_ptr<ValueType>() : any_nullptr;
+}
+
+template<class ValueType >
+any_nodiscard inline ValueType * any_cast( any * operand ) any_noexcept
+{
+    return operand != any_nullptr && operand->type() == typeid(ValueType) ? operand->to_ptr<ValueType>() : any_nullptr;
+}
+
+} // namespace any_lite
+
+using namespace any_lite;
+
+} // namespace nonstd
+
+#endif // any_USES_STD_ANY
+
+#endif // NONSTD_ANY_LITE_HPP