tomoto 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/LICENSE.txt +1 -1
- data/README.md +3 -3
- data/ext/tomoto/ext.cpp +34 -9
- data/ext/tomoto/extconf.rb +2 -1
- data/lib/tomoto/dmr.rb +1 -1
- data/lib/tomoto/gdmr.rb +1 -1
- data/lib/tomoto/version.rb +1 -1
- data/vendor/tomotopy/LICENSE +1 -1
- data/vendor/tomotopy/README.kr.rst +32 -3
- data/vendor/tomotopy/README.rst +30 -1
- data/vendor/tomotopy/src/Labeling/FoRelevance.cpp +133 -147
- data/vendor/tomotopy/src/Labeling/FoRelevance.h +158 -5
- data/vendor/tomotopy/src/TopicModel/DMR.h +1 -16
- data/vendor/tomotopy/src/TopicModel/DMRModel.hpp +15 -34
- data/vendor/tomotopy/src/TopicModel/DT.h +1 -16
- data/vendor/tomotopy/src/TopicModel/DTModel.hpp +15 -32
- data/vendor/tomotopy/src/TopicModel/GDMRModel.hpp +18 -37
- data/vendor/tomotopy/src/TopicModel/HDPModel.hpp +16 -20
- data/vendor/tomotopy/src/TopicModel/HLDAModel.hpp +3 -3
- data/vendor/tomotopy/src/TopicModel/LDA.h +0 -11
- data/vendor/tomotopy/src/TopicModel/LDAModel.hpp +9 -21
- data/vendor/tomotopy/src/TopicModel/LLDA.h +0 -15
- data/vendor/tomotopy/src/TopicModel/LLDAModel.hpp +12 -30
- data/vendor/tomotopy/src/TopicModel/MGLDA.h +0 -15
- data/vendor/tomotopy/src/TopicModel/MGLDAModel.hpp +59 -72
- data/vendor/tomotopy/src/TopicModel/PLDAModel.hpp +12 -30
- data/vendor/tomotopy/src/TopicModel/SLDA.h +0 -15
- data/vendor/tomotopy/src/TopicModel/SLDAModel.hpp +17 -35
- data/vendor/tomotopy/src/TopicModel/TopicModel.hpp +158 -38
- data/vendor/tomotopy/src/Utils/Dictionary.h +40 -2
- data/vendor/tomotopy/src/Utils/EigenAddonOps.hpp +122 -3
- data/vendor/tomotopy/src/Utils/SharedString.hpp +181 -0
- data/vendor/tomotopy/src/Utils/math.h +1 -1
- data/vendor/tomotopy/src/Utils/sample.hpp +1 -1
- data/vendor/tomotopy/src/Utils/serializer.hpp +17 -0
- data/vendor/variant/LICENSE +25 -0
- data/vendor/variant/LICENSE_1_0.txt +23 -0
- data/vendor/variant/README.md +102 -0
- data/vendor/variant/include/mapbox/optional.hpp +74 -0
- data/vendor/variant/include/mapbox/recursive_wrapper.hpp +122 -0
- data/vendor/variant/include/mapbox/variant.hpp +974 -0
- data/vendor/variant/include/mapbox/variant_io.hpp +45 -0
- metadata +15 -7
@@ -0,0 +1,25 @@
|
|
1
|
+
Copyright (c) MapBox
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without modification,
|
5
|
+
are permitted provided that the following conditions are met:
|
6
|
+
|
7
|
+
- Redistributions of source code must retain the above copyright notice, this
|
8
|
+
list of conditions and the following disclaimer.
|
9
|
+
- Redistributions in binary form must reproduce the above copyright notice, this
|
10
|
+
list of conditions and the following disclaimer in the documentation and/or
|
11
|
+
other materials provided with the distribution.
|
12
|
+
- Neither the name "MapBox" nor the names of its contributors may be
|
13
|
+
used to endorse or promote products derived from this software without
|
14
|
+
specific prior written permission.
|
15
|
+
|
16
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
17
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
18
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
19
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
20
|
+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
21
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
22
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
23
|
+
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
24
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
25
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
@@ -0,0 +1,23 @@
|
|
1
|
+
Boost Software License - Version 1.0 - August 17th, 2003
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person or organization
|
4
|
+
obtaining a copy of the software and accompanying documentation covered by
|
5
|
+
this license (the "Software") to use, reproduce, display, distribute,
|
6
|
+
execute, and transmit the Software, and to prepare derivative works of the
|
7
|
+
Software, and to permit third-parties to whom the Software is furnished to
|
8
|
+
do so, all subject to the following:
|
9
|
+
|
10
|
+
The copyright notices in the Software and this entire statement, including
|
11
|
+
the above license grant, this restriction and the following disclaimer,
|
12
|
+
must be included in all copies of the Software, in whole or in part, and
|
13
|
+
all derivative works of the Software, unless such copies or derivative
|
14
|
+
works are solely in the form of machine-executable object code generated by
|
15
|
+
a source language processor.
|
16
|
+
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
20
|
+
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
21
|
+
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
22
|
+
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
23
|
+
DEALINGS IN THE SOFTWARE.
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# Mapbox Variant
|
2
|
+
|
3
|
+
An alternative to `boost::variant` for C++11 and C++14
|
4
|
+
|
5
|
+
[](https://travis-ci.org/mapbox/variant)
|
6
|
+
[](https://ci.appveyor.com/project/Mapbox/variant)
|
7
|
+
[](https://coveralls.io/r/mapbox/variant?branch=master)
|
8
|
+
|
9
|
+
|
10
|
+
## Why use Mapbox Variant?
|
11
|
+
|
12
|
+
Mapbox variant has the same speedy performance of `boost::variant` but is
|
13
|
+
faster to compile, results in smaller binaries, and has no dependencies.
|
14
|
+
|
15
|
+
For example on OS X 10.9 with clang++ and libc++:
|
16
|
+
|
17
|
+
Test | Mapbox Variant | Boost Variant
|
18
|
+
---- | -------------- | -------------
|
19
|
+
Size of pre-compiled header (release / debug) | 2.8/2.8 MB | 12/15 MB
|
20
|
+
Size of simple program linking variant (release / debug) | 8/24 K | 12/40 K
|
21
|
+
Time to compile header | 185 ms | 675 ms
|
22
|
+
|
23
|
+
(Numbers from an older version of Mapbox variant.)
|
24
|
+
|
25
|
+
|
26
|
+
## Goals
|
27
|
+
|
28
|
+
Mapbox `variant` has been a very valuable, lightweight alternative for apps
|
29
|
+
that can use c++11 or c++14 but that do not want a boost dependency.
|
30
|
+
Mapbox `variant` has also been useful in apps that do depend on boost, like
|
31
|
+
mapnik, to help (slightly) with compile times and to majorly lessen dependence
|
32
|
+
on boost in core headers. The original goal and near term goal is to maintain
|
33
|
+
external API compatibility with `boost::variant` such that Mapbox `variant`
|
34
|
+
can be a "drop in". At the same time the goal is to stay minimal: Only
|
35
|
+
implement the features that are actually needed in existing software. So being
|
36
|
+
an "incomplete" implementation is just fine.
|
37
|
+
|
38
|
+
Currently Mapbox variant doesn't try to be API compatible with the upcoming
|
39
|
+
variant standard, because the standard is not finished and it would be too much
|
40
|
+
work. But we'll revisit this decision in the future if needed.
|
41
|
+
|
42
|
+
If Mapbox variant is not for you, have a look at [these other
|
43
|
+
implementations](doc/other_implementations.md).
|
44
|
+
|
45
|
+
Want to know more about the upcoming standard? Have a look at our
|
46
|
+
[overview](doc/standards_effort.md).
|
47
|
+
|
48
|
+
|
49
|
+
## Depends
|
50
|
+
|
51
|
+
- Compiler supporting `-std=c++11` or `-std=c++14`
|
52
|
+
|
53
|
+
Tested with:
|
54
|
+
|
55
|
+
- g++-4.7
|
56
|
+
- g++-4.8
|
57
|
+
- g++-4.9
|
58
|
+
- g++-5.2
|
59
|
+
- clang++-3.5
|
60
|
+
- clang++-3.6
|
61
|
+
- clang++-3.7
|
62
|
+
- clang++-3.8
|
63
|
+
- clang++-3.9
|
64
|
+
- Visual Studio 2015
|
65
|
+
|
66
|
+
## Usage
|
67
|
+
|
68
|
+
There is nothing to build, just include `variant.hpp` in your project. Include `variant_io.hpp` if you need
|
69
|
+
the `operator<<` overload for variant.
|
70
|
+
|
71
|
+
|
72
|
+
## Unit Tests
|
73
|
+
|
74
|
+
On Unix systems compile and run the unit tests with `make test`.
|
75
|
+
|
76
|
+
On Windows run `scripts/build-local.bat`.
|
77
|
+
|
78
|
+
|
79
|
+
## Limitations
|
80
|
+
|
81
|
+
* The `variant` can not hold references (something like `variant<int&>` is
|
82
|
+
not possible). You might want to try `std::reference_wrapper` instead.
|
83
|
+
|
84
|
+
|
85
|
+
## Deprecations
|
86
|
+
|
87
|
+
* The included implementation of `optional` is deprecated and will be removed
|
88
|
+
in a future version. See https://github.com/mapbox/variant/issues/64.
|
89
|
+
* Old versions of the code needed visitors to derive from `static_visitor`.
|
90
|
+
This is not needed any more and marked as deprecated. The `static_visitor`
|
91
|
+
class will be removed in future versions.
|
92
|
+
|
93
|
+
|
94
|
+
## Benchmarks
|
95
|
+
|
96
|
+
make bench
|
97
|
+
|
98
|
+
|
99
|
+
## Check object sizes
|
100
|
+
|
101
|
+
make sizes /path/to/boost/variant.hpp
|
102
|
+
|
@@ -0,0 +1,74 @@
|
|
1
|
+
#ifndef MAPBOX_UTIL_OPTIONAL_HPP
|
2
|
+
#define MAPBOX_UTIL_OPTIONAL_HPP
|
3
|
+
|
4
|
+
#pragma message("This implementation of optional is deprecated. See https://github.com/mapbox/variant/issues/64.")
|
5
|
+
|
6
|
+
#include <type_traits>
|
7
|
+
#include <utility>
|
8
|
+
|
9
|
+
#include <mapbox/variant.hpp>
|
10
|
+
|
11
|
+
namespace mapbox {
|
12
|
+
namespace util {
|
13
|
+
|
14
|
+
template <typename T>
|
15
|
+
class optional
|
16
|
+
{
|
17
|
+
static_assert(!std::is_reference<T>::value, "optional doesn't support references");
|
18
|
+
|
19
|
+
struct none_type
|
20
|
+
{
|
21
|
+
};
|
22
|
+
|
23
|
+
variant<none_type, T> variant_;
|
24
|
+
|
25
|
+
public:
|
26
|
+
optional() = default;
|
27
|
+
|
28
|
+
optional(optional const& rhs)
|
29
|
+
{
|
30
|
+
if (this != &rhs)
|
31
|
+
{ // protect against invalid self-assignment
|
32
|
+
variant_ = rhs.variant_;
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
optional(T const& v) { variant_ = v; }
|
37
|
+
|
38
|
+
explicit operator bool() const noexcept { return variant_.template is<T>(); }
|
39
|
+
|
40
|
+
T const& get() const { return variant_.template get<T>(); }
|
41
|
+
T& get() { return variant_.template get<T>(); }
|
42
|
+
|
43
|
+
T const& operator*() const { return this->get(); }
|
44
|
+
T operator*() { return this->get(); }
|
45
|
+
|
46
|
+
optional& operator=(T const& v)
|
47
|
+
{
|
48
|
+
variant_ = v;
|
49
|
+
return *this;
|
50
|
+
}
|
51
|
+
|
52
|
+
optional& operator=(optional const& rhs)
|
53
|
+
{
|
54
|
+
if (this != &rhs)
|
55
|
+
{
|
56
|
+
variant_ = rhs.variant_;
|
57
|
+
}
|
58
|
+
return *this;
|
59
|
+
}
|
60
|
+
|
61
|
+
template <typename... Args>
|
62
|
+
void emplace(Args&&... args)
|
63
|
+
{
|
64
|
+
variant_ = T{std::forward<Args>(args)...};
|
65
|
+
}
|
66
|
+
|
67
|
+
void reset() { variant_ = none_type{}; }
|
68
|
+
|
69
|
+
}; // class optional
|
70
|
+
|
71
|
+
} // namespace util
|
72
|
+
} // namespace mapbox
|
73
|
+
|
74
|
+
#endif // MAPBOX_UTIL_OPTIONAL_HPP
|
@@ -0,0 +1,122 @@
|
|
1
|
+
#ifndef MAPBOX_UTIL_RECURSIVE_WRAPPER_HPP
|
2
|
+
#define MAPBOX_UTIL_RECURSIVE_WRAPPER_HPP
|
3
|
+
|
4
|
+
// Based on variant/recursive_wrapper.hpp from boost.
|
5
|
+
//
|
6
|
+
// Original license:
|
7
|
+
//
|
8
|
+
// Copyright (c) 2002-2003
|
9
|
+
// Eric Friedman, Itay Maman
|
10
|
+
//
|
11
|
+
// Distributed under the Boost Software License, Version 1.0. (See
|
12
|
+
// accompanying file LICENSE_1_0.txt or copy at
|
13
|
+
// http://www.boost.org/LICENSE_1_0.txt)
|
14
|
+
|
15
|
+
#include <cassert>
|
16
|
+
#include <utility>
|
17
|
+
|
18
|
+
namespace mapbox {
|
19
|
+
namespace util {
|
20
|
+
|
21
|
+
template <typename T>
|
22
|
+
class recursive_wrapper
|
23
|
+
{
|
24
|
+
|
25
|
+
T* p_;
|
26
|
+
|
27
|
+
void assign(T const& rhs)
|
28
|
+
{
|
29
|
+
this->get() = rhs;
|
30
|
+
}
|
31
|
+
|
32
|
+
public:
|
33
|
+
using type = T;
|
34
|
+
|
35
|
+
/**
|
36
|
+
* Default constructor default initializes the internally stored value.
|
37
|
+
* For POD types this means nothing is done and the storage is
|
38
|
+
* uninitialized.
|
39
|
+
*
|
40
|
+
* @throws std::bad_alloc if there is insufficient memory for an object
|
41
|
+
* of type T.
|
42
|
+
* @throws any exception thrown by the default constructur of T.
|
43
|
+
*/
|
44
|
+
recursive_wrapper()
|
45
|
+
: p_(new T){}
|
46
|
+
|
47
|
+
~recursive_wrapper() noexcept { delete p_; }
|
48
|
+
|
49
|
+
recursive_wrapper(recursive_wrapper const& operand)
|
50
|
+
: p_(new T(operand.get())) {}
|
51
|
+
|
52
|
+
recursive_wrapper(T const& operand)
|
53
|
+
: p_(new T(operand)) {}
|
54
|
+
|
55
|
+
recursive_wrapper(recursive_wrapper&& operand)
|
56
|
+
: p_(new T(std::move(operand.get()))) {}
|
57
|
+
|
58
|
+
recursive_wrapper(T&& operand)
|
59
|
+
: p_(new T(std::move(operand))) {}
|
60
|
+
|
61
|
+
inline recursive_wrapper& operator=(recursive_wrapper const& rhs)
|
62
|
+
{
|
63
|
+
assign(rhs.get());
|
64
|
+
return *this;
|
65
|
+
}
|
66
|
+
|
67
|
+
inline recursive_wrapper& operator=(T const& rhs)
|
68
|
+
{
|
69
|
+
assign(rhs);
|
70
|
+
return *this;
|
71
|
+
}
|
72
|
+
|
73
|
+
inline void swap(recursive_wrapper& operand) noexcept
|
74
|
+
{
|
75
|
+
T* temp = operand.p_;
|
76
|
+
operand.p_ = p_;
|
77
|
+
p_ = temp;
|
78
|
+
}
|
79
|
+
|
80
|
+
recursive_wrapper& operator=(recursive_wrapper&& rhs) noexcept
|
81
|
+
{
|
82
|
+
swap(rhs);
|
83
|
+
return *this;
|
84
|
+
}
|
85
|
+
|
86
|
+
recursive_wrapper& operator=(T&& rhs)
|
87
|
+
{
|
88
|
+
get() = std::move(rhs);
|
89
|
+
return *this;
|
90
|
+
}
|
91
|
+
|
92
|
+
T& get()
|
93
|
+
{
|
94
|
+
assert(p_);
|
95
|
+
return *get_pointer();
|
96
|
+
}
|
97
|
+
|
98
|
+
T const& get() const
|
99
|
+
{
|
100
|
+
assert(p_);
|
101
|
+
return *get_pointer();
|
102
|
+
}
|
103
|
+
|
104
|
+
T* get_pointer() { return p_; }
|
105
|
+
|
106
|
+
const T* get_pointer() const { return p_; }
|
107
|
+
|
108
|
+
operator T const&() const { return this->get(); }
|
109
|
+
|
110
|
+
operator T&() { return this->get(); }
|
111
|
+
|
112
|
+
}; // class recursive_wrapper
|
113
|
+
|
114
|
+
template <typename T>
|
115
|
+
inline void swap(recursive_wrapper<T>& lhs, recursive_wrapper<T>& rhs) noexcept
|
116
|
+
{
|
117
|
+
lhs.swap(rhs);
|
118
|
+
}
|
119
|
+
} // namespace util
|
120
|
+
} // namespace mapbox
|
121
|
+
|
122
|
+
#endif // MAPBOX_UTIL_RECURSIVE_WRAPPER_HPP
|
@@ -0,0 +1,974 @@
|
|
1
|
+
#ifndef MAPBOX_UTIL_VARIANT_HPP
|
2
|
+
#define MAPBOX_UTIL_VARIANT_HPP
|
3
|
+
|
4
|
+
#include <cassert>
|
5
|
+
#include <cstddef> // size_t
|
6
|
+
#include <new> // operator new
|
7
|
+
#include <stdexcept> // runtime_error
|
8
|
+
#include <string>
|
9
|
+
#include <tuple>
|
10
|
+
#include <type_traits>
|
11
|
+
#include <typeinfo>
|
12
|
+
#include <utility>
|
13
|
+
|
14
|
+
#include <mapbox/recursive_wrapper.hpp>
|
15
|
+
|
16
|
+
// clang-format off
|
17
|
+
// [[deprecated]] is only available in C++14, use this for the time being
|
18
|
+
#if __cplusplus <= 201103L
|
19
|
+
# ifdef __GNUC__
|
20
|
+
# define MAPBOX_VARIANT_DEPRECATED __attribute__((deprecated))
|
21
|
+
# elif defined(_MSC_VER)
|
22
|
+
# define MAPBOX_VARIANT_DEPRECATED __declspec(deprecated)
|
23
|
+
# else
|
24
|
+
# define MAPBOX_VARIANT_DEPRECATED
|
25
|
+
# endif
|
26
|
+
#else
|
27
|
+
# define MAPBOX_VARIANT_DEPRECATED [[deprecated]]
|
28
|
+
#endif
|
29
|
+
|
30
|
+
|
31
|
+
#ifdef _MSC_VER
|
32
|
+
// https://msdn.microsoft.com/en-us/library/bw1hbe6y.aspx
|
33
|
+
# ifdef NDEBUG
|
34
|
+
# define VARIANT_INLINE __forceinline
|
35
|
+
# else
|
36
|
+
# define VARIANT_INLINE //__declspec(noinline)
|
37
|
+
# endif
|
38
|
+
#else
|
39
|
+
# ifdef NDEBUG
|
40
|
+
# define VARIANT_INLINE //inline __attribute__((always_inline))
|
41
|
+
# else
|
42
|
+
# define VARIANT_INLINE __attribute__((noinline))
|
43
|
+
# endif
|
44
|
+
#endif
|
45
|
+
// clang-format on
|
46
|
+
|
47
|
+
// Exceptions
|
48
|
+
#if defined( __EXCEPTIONS) || defined( _MSC_VER)
|
49
|
+
#define HAS_EXCEPTIONS
|
50
|
+
#endif
|
51
|
+
|
52
|
+
#define VARIANT_MAJOR_VERSION 1
|
53
|
+
#define VARIANT_MINOR_VERSION 1
|
54
|
+
#define VARIANT_PATCH_VERSION 0
|
55
|
+
|
56
|
+
#define VARIANT_VERSION (VARIANT_MAJOR_VERSION * 100000) + (VARIANT_MINOR_VERSION * 100) + (VARIANT_PATCH_VERSION)
|
57
|
+
|
58
|
+
namespace mapbox {
|
59
|
+
namespace util {
|
60
|
+
|
61
|
+
// XXX This should derive from std::logic_error instead of std::runtime_error.
|
62
|
+
// See https://github.com/mapbox/variant/issues/48 for details.
|
63
|
+
class bad_variant_access : public std::runtime_error
|
64
|
+
{
|
65
|
+
|
66
|
+
public:
|
67
|
+
explicit bad_variant_access(const std::string& what_arg)
|
68
|
+
: runtime_error(what_arg) {}
|
69
|
+
|
70
|
+
explicit bad_variant_access(const char* what_arg)
|
71
|
+
: runtime_error(what_arg) {}
|
72
|
+
|
73
|
+
}; // class bad_variant_access
|
74
|
+
|
75
|
+
template <typename R = void>
|
76
|
+
struct MAPBOX_VARIANT_DEPRECATED static_visitor
|
77
|
+
{
|
78
|
+
using result_type = R;
|
79
|
+
|
80
|
+
protected:
|
81
|
+
static_visitor() {}
|
82
|
+
~static_visitor() {}
|
83
|
+
};
|
84
|
+
|
85
|
+
namespace detail {
|
86
|
+
|
87
|
+
static constexpr std::size_t invalid_value = std::size_t(-1);
|
88
|
+
|
89
|
+
template <typename T, typename... Types>
|
90
|
+
struct direct_type;
|
91
|
+
|
92
|
+
template <typename T, typename First, typename... Types>
|
93
|
+
struct direct_type<T, First, Types...>
|
94
|
+
{
|
95
|
+
static constexpr std::size_t index = std::is_same<T, First>::value
|
96
|
+
? sizeof...(Types)
|
97
|
+
: direct_type<T, Types...>::index;
|
98
|
+
};
|
99
|
+
|
100
|
+
template <typename T>
|
101
|
+
struct direct_type<T>
|
102
|
+
{
|
103
|
+
static constexpr std::size_t index = invalid_value;
|
104
|
+
};
|
105
|
+
|
106
|
+
#if __cpp_lib_logical_traits >= 201510L
|
107
|
+
|
108
|
+
using std::disjunction;
|
109
|
+
|
110
|
+
#else
|
111
|
+
|
112
|
+
template <typename...>
|
113
|
+
struct disjunction : std::false_type {};
|
114
|
+
|
115
|
+
template <typename B1>
|
116
|
+
struct disjunction<B1> : B1 {};
|
117
|
+
|
118
|
+
template <typename B1, typename B2>
|
119
|
+
struct disjunction<B1, B2> : std::conditional<B1::value, B1, B2>::type {};
|
120
|
+
|
121
|
+
template <typename B1, typename... Bs>
|
122
|
+
struct disjunction<B1, Bs...> : std::conditional<B1::value, B1, disjunction<Bs...>>::type {};
|
123
|
+
|
124
|
+
#endif
|
125
|
+
|
126
|
+
template <typename T, typename... Types>
|
127
|
+
struct convertible_type;
|
128
|
+
|
129
|
+
template <typename T, typename First, typename... Types>
|
130
|
+
struct convertible_type<T, First, Types...>
|
131
|
+
{
|
132
|
+
static constexpr std::size_t index = std::is_convertible<T, First>::value
|
133
|
+
? disjunction<std::is_convertible<T, Types>...>::value ? invalid_value : sizeof...(Types)
|
134
|
+
: convertible_type<T, Types...>::index;
|
135
|
+
};
|
136
|
+
|
137
|
+
template <typename T>
|
138
|
+
struct convertible_type<T>
|
139
|
+
{
|
140
|
+
static constexpr std::size_t index = invalid_value;
|
141
|
+
};
|
142
|
+
|
143
|
+
template <typename T, typename... Types>
|
144
|
+
struct value_traits
|
145
|
+
{
|
146
|
+
using value_type = typename std::remove_const<typename std::remove_reference<T>::type>::type;
|
147
|
+
static constexpr std::size_t direct_index = direct_type<value_type, Types...>::index;
|
148
|
+
static constexpr bool is_direct = direct_index != invalid_value;
|
149
|
+
static constexpr std::size_t index = is_direct ? direct_index : convertible_type<value_type, Types...>::index;
|
150
|
+
static constexpr bool is_valid = index != invalid_value;
|
151
|
+
static constexpr std::size_t tindex = is_valid ? sizeof...(Types)-index : 0;
|
152
|
+
using target_type = typename std::tuple_element<tindex, std::tuple<void, Types...>>::type;
|
153
|
+
};
|
154
|
+
|
155
|
+
template <typename T, typename R = void>
|
156
|
+
struct enable_if_type
|
157
|
+
{
|
158
|
+
using type = R;
|
159
|
+
};
|
160
|
+
|
161
|
+
template <typename F, typename V, typename Enable = void>
|
162
|
+
struct result_of_unary_visit
|
163
|
+
{
|
164
|
+
using type = typename std::result_of<F(V&)>::type;
|
165
|
+
};
|
166
|
+
|
167
|
+
template <typename F, typename V>
|
168
|
+
struct result_of_unary_visit<F, V, typename enable_if_type<typename F::result_type>::type>
|
169
|
+
{
|
170
|
+
using type = typename F::result_type;
|
171
|
+
};
|
172
|
+
|
173
|
+
template <typename F, typename V, typename Enable = void>
|
174
|
+
struct result_of_binary_visit
|
175
|
+
{
|
176
|
+
using type = typename std::result_of<F(V&, V&)>::type;
|
177
|
+
};
|
178
|
+
|
179
|
+
template <typename F, typename V>
|
180
|
+
struct result_of_binary_visit<F, V, typename enable_if_type<typename F::result_type>::type>
|
181
|
+
{
|
182
|
+
using type = typename F::result_type;
|
183
|
+
};
|
184
|
+
|
185
|
+
template <std::size_t arg1, std::size_t... others>
|
186
|
+
struct static_max;
|
187
|
+
|
188
|
+
template <std::size_t arg>
|
189
|
+
struct static_max<arg>
|
190
|
+
{
|
191
|
+
static const std::size_t value = arg;
|
192
|
+
};
|
193
|
+
|
194
|
+
template <std::size_t arg1, std::size_t arg2, std::size_t... others>
|
195
|
+
struct static_max<arg1, arg2, others...>
|
196
|
+
{
|
197
|
+
static const std::size_t value = arg1 >= arg2 ? static_max<arg1, others...>::value : static_max<arg2, others...>::value;
|
198
|
+
};
|
199
|
+
|
200
|
+
template <typename... Types>
|
201
|
+
struct variant_helper;
|
202
|
+
|
203
|
+
template <typename T, typename... Types>
|
204
|
+
struct variant_helper<T, Types...>
|
205
|
+
{
|
206
|
+
VARIANT_INLINE static void destroy(const std::size_t type_index, void* data)
|
207
|
+
{
|
208
|
+
if (type_index == sizeof...(Types))
|
209
|
+
{
|
210
|
+
reinterpret_cast<T*>(data)->~T();
|
211
|
+
}
|
212
|
+
else
|
213
|
+
{
|
214
|
+
variant_helper<Types...>::destroy(type_index, data);
|
215
|
+
}
|
216
|
+
}
|
217
|
+
|
218
|
+
VARIANT_INLINE static void move(const std::size_t old_type_index, void* old_value, void* new_value)
|
219
|
+
{
|
220
|
+
if (old_type_index == sizeof...(Types))
|
221
|
+
{
|
222
|
+
new (new_value) T(std::move(*reinterpret_cast<T*>(old_value)));
|
223
|
+
}
|
224
|
+
else
|
225
|
+
{
|
226
|
+
variant_helper<Types...>::move(old_type_index, old_value, new_value);
|
227
|
+
}
|
228
|
+
}
|
229
|
+
|
230
|
+
VARIANT_INLINE static void copy(const std::size_t old_type_index, const void* old_value, void* new_value)
|
231
|
+
{
|
232
|
+
if (old_type_index == sizeof...(Types))
|
233
|
+
{
|
234
|
+
new (new_value) T(*reinterpret_cast<const T*>(old_value));
|
235
|
+
}
|
236
|
+
else
|
237
|
+
{
|
238
|
+
variant_helper<Types...>::copy(old_type_index, old_value, new_value);
|
239
|
+
}
|
240
|
+
}
|
241
|
+
};
|
242
|
+
|
243
|
+
template <>
|
244
|
+
struct variant_helper<>
|
245
|
+
{
|
246
|
+
VARIANT_INLINE static void destroy(const std::size_t, void*) {}
|
247
|
+
VARIANT_INLINE static void move(const std::size_t, void*, void*) {}
|
248
|
+
VARIANT_INLINE static void copy(const std::size_t, const void*, void*) {}
|
249
|
+
};
|
250
|
+
|
251
|
+
template <typename T>
|
252
|
+
struct unwrapper
|
253
|
+
{
|
254
|
+
static T const& apply_const(T const& obj) { return obj; }
|
255
|
+
static T& apply(T& obj) { return obj; }
|
256
|
+
};
|
257
|
+
|
258
|
+
template <typename T>
|
259
|
+
struct unwrapper<recursive_wrapper<T>>
|
260
|
+
{
|
261
|
+
static auto apply_const(recursive_wrapper<T> const& obj)
|
262
|
+
-> typename recursive_wrapper<T>::type const&
|
263
|
+
{
|
264
|
+
return obj.get();
|
265
|
+
}
|
266
|
+
static auto apply(recursive_wrapper<T>& obj)
|
267
|
+
-> typename recursive_wrapper<T>::type&
|
268
|
+
{
|
269
|
+
return obj.get();
|
270
|
+
}
|
271
|
+
};
|
272
|
+
|
273
|
+
template <typename T>
|
274
|
+
struct unwrapper<std::reference_wrapper<T>>
|
275
|
+
{
|
276
|
+
static auto apply_const(std::reference_wrapper<T> const& obj)
|
277
|
+
-> typename std::reference_wrapper<T>::type const&
|
278
|
+
{
|
279
|
+
return obj.get();
|
280
|
+
}
|
281
|
+
static auto apply(std::reference_wrapper<T>& obj)
|
282
|
+
-> typename std::reference_wrapper<T>::type&
|
283
|
+
{
|
284
|
+
return obj.get();
|
285
|
+
}
|
286
|
+
};
|
287
|
+
|
288
|
+
template <typename F, typename V, typename R, typename... Types>
|
289
|
+
struct dispatcher;
|
290
|
+
|
291
|
+
template <typename F, typename V, typename R, typename T, typename... Types>
|
292
|
+
struct dispatcher<F, V, R, T, Types...>
|
293
|
+
{
|
294
|
+
VARIANT_INLINE static R apply_const(V const& v, F&& f)
|
295
|
+
{
|
296
|
+
if (v.template is<T>())
|
297
|
+
{
|
298
|
+
return f(unwrapper<T>::apply_const(v.template get_unchecked<T>()));
|
299
|
+
}
|
300
|
+
else
|
301
|
+
{
|
302
|
+
return dispatcher<F, V, R, Types...>::apply_const(v, std::forward<F>(f));
|
303
|
+
}
|
304
|
+
}
|
305
|
+
|
306
|
+
VARIANT_INLINE static R apply(V& v, F&& f)
|
307
|
+
{
|
308
|
+
if (v.template is<T>())
|
309
|
+
{
|
310
|
+
return f(unwrapper<T>::apply(v.template get_unchecked<T>()));
|
311
|
+
}
|
312
|
+
else
|
313
|
+
{
|
314
|
+
return dispatcher<F, V, R, Types...>::apply(v, std::forward<F>(f));
|
315
|
+
}
|
316
|
+
}
|
317
|
+
};
|
318
|
+
|
319
|
+
template <typename F, typename V, typename R, typename T>
|
320
|
+
struct dispatcher<F, V, R, T>
|
321
|
+
{
|
322
|
+
VARIANT_INLINE static R apply_const(V const& v, F&& f)
|
323
|
+
{
|
324
|
+
return f(unwrapper<T>::apply_const(v.template get_unchecked<T>()));
|
325
|
+
}
|
326
|
+
|
327
|
+
VARIANT_INLINE static R apply(V& v, F&& f)
|
328
|
+
{
|
329
|
+
return f(unwrapper<T>::apply(v.template get_unchecked<T>()));
|
330
|
+
}
|
331
|
+
};
|
332
|
+
|
333
|
+
template <typename F, typename V, typename R, typename T, typename... Types>
|
334
|
+
struct binary_dispatcher_rhs;
|
335
|
+
|
336
|
+
template <typename F, typename V, typename R, typename T0, typename T1, typename... Types>
|
337
|
+
struct binary_dispatcher_rhs<F, V, R, T0, T1, Types...>
|
338
|
+
{
|
339
|
+
VARIANT_INLINE static R apply_const(V const& lhs, V const& rhs, F&& f)
|
340
|
+
{
|
341
|
+
if (rhs.template is<T1>()) // call binary functor
|
342
|
+
{
|
343
|
+
return f(unwrapper<T0>::apply_const(lhs.template get_unchecked<T0>()),
|
344
|
+
unwrapper<T1>::apply_const(rhs.template get_unchecked<T1>()));
|
345
|
+
}
|
346
|
+
else
|
347
|
+
{
|
348
|
+
return binary_dispatcher_rhs<F, V, R, T0, Types...>::apply_const(lhs, rhs, std::forward<F>(f));
|
349
|
+
}
|
350
|
+
}
|
351
|
+
|
352
|
+
VARIANT_INLINE static R apply(V& lhs, V& rhs, F&& f)
|
353
|
+
{
|
354
|
+
if (rhs.template is<T1>()) // call binary functor
|
355
|
+
{
|
356
|
+
return f(unwrapper<T0>::apply(lhs.template get_unchecked<T0>()),
|
357
|
+
unwrapper<T1>::apply(rhs.template get_unchecked<T1>()));
|
358
|
+
}
|
359
|
+
else
|
360
|
+
{
|
361
|
+
return binary_dispatcher_rhs<F, V, R, T0, Types...>::apply(lhs, rhs, std::forward<F>(f));
|
362
|
+
}
|
363
|
+
}
|
364
|
+
};
|
365
|
+
|
366
|
+
template <typename F, typename V, typename R, typename T0, typename T1>
|
367
|
+
struct binary_dispatcher_rhs<F, V, R, T0, T1>
|
368
|
+
{
|
369
|
+
VARIANT_INLINE static R apply_const(V const& lhs, V const& rhs, F&& f)
|
370
|
+
{
|
371
|
+
return f(unwrapper<T0>::apply_const(lhs.template get_unchecked<T0>()),
|
372
|
+
unwrapper<T1>::apply_const(rhs.template get_unchecked<T1>()));
|
373
|
+
}
|
374
|
+
|
375
|
+
VARIANT_INLINE static R apply(V& lhs, V& rhs, F&& f)
|
376
|
+
{
|
377
|
+
return f(unwrapper<T0>::apply(lhs.template get_unchecked<T0>()),
|
378
|
+
unwrapper<T1>::apply(rhs.template get_unchecked<T1>()));
|
379
|
+
}
|
380
|
+
};
|
381
|
+
|
382
|
+
template <typename F, typename V, typename R, typename T, typename... Types>
|
383
|
+
struct binary_dispatcher_lhs;
|
384
|
+
|
385
|
+
template <typename F, typename V, typename R, typename T0, typename T1, typename... Types>
|
386
|
+
struct binary_dispatcher_lhs<F, V, R, T0, T1, Types...>
|
387
|
+
{
|
388
|
+
VARIANT_INLINE static R apply_const(V const& lhs, V const& rhs, F&& f)
|
389
|
+
{
|
390
|
+
if (lhs.template is<T1>()) // call binary functor
|
391
|
+
{
|
392
|
+
return f(unwrapper<T1>::apply_const(lhs.template get_unchecked<T1>()),
|
393
|
+
unwrapper<T0>::apply_const(rhs.template get_unchecked<T0>()));
|
394
|
+
}
|
395
|
+
else
|
396
|
+
{
|
397
|
+
return binary_dispatcher_lhs<F, V, R, T0, Types...>::apply_const(lhs, rhs, std::forward<F>(f));
|
398
|
+
}
|
399
|
+
}
|
400
|
+
|
401
|
+
VARIANT_INLINE static R apply(V& lhs, V& rhs, F&& f)
|
402
|
+
{
|
403
|
+
if (lhs.template is<T1>()) // call binary functor
|
404
|
+
{
|
405
|
+
return f(unwrapper<T1>::apply(lhs.template get_unchecked<T1>()),
|
406
|
+
unwrapper<T0>::apply(rhs.template get_unchecked<T0>()));
|
407
|
+
}
|
408
|
+
else
|
409
|
+
{
|
410
|
+
return binary_dispatcher_lhs<F, V, R, T0, Types...>::apply(lhs, rhs, std::forward<F>(f));
|
411
|
+
}
|
412
|
+
}
|
413
|
+
};
|
414
|
+
|
415
|
+
template <typename F, typename V, typename R, typename T0, typename T1>
|
416
|
+
struct binary_dispatcher_lhs<F, V, R, T0, T1>
|
417
|
+
{
|
418
|
+
VARIANT_INLINE static R apply_const(V const& lhs, V const& rhs, F&& f)
|
419
|
+
{
|
420
|
+
return f(unwrapper<T1>::apply_const(lhs.template get_unchecked<T1>()),
|
421
|
+
unwrapper<T0>::apply_const(rhs.template get_unchecked<T0>()));
|
422
|
+
}
|
423
|
+
|
424
|
+
VARIANT_INLINE static R apply(V& lhs, V& rhs, F&& f)
|
425
|
+
{
|
426
|
+
return f(unwrapper<T1>::apply(lhs.template get_unchecked<T1>()),
|
427
|
+
unwrapper<T0>::apply(rhs.template get_unchecked<T0>()));
|
428
|
+
}
|
429
|
+
};
|
430
|
+
|
431
|
+
template <typename F, typename V, typename R, typename... Types>
|
432
|
+
struct binary_dispatcher;
|
433
|
+
|
434
|
+
template <typename F, typename V, typename R, typename T, typename... Types>
|
435
|
+
struct binary_dispatcher<F, V, R, T, Types...>
|
436
|
+
{
|
437
|
+
VARIANT_INLINE static R apply_const(V const& v0, V const& v1, F&& f)
|
438
|
+
{
|
439
|
+
if (v0.template is<T>())
|
440
|
+
{
|
441
|
+
if (v1.template is<T>())
|
442
|
+
{
|
443
|
+
return f(unwrapper<T>::apply_const(v0.template get_unchecked<T>()),
|
444
|
+
unwrapper<T>::apply_const(v1.template get_unchecked<T>())); // call binary functor
|
445
|
+
}
|
446
|
+
else
|
447
|
+
{
|
448
|
+
return binary_dispatcher_rhs<F, V, R, T, Types...>::apply_const(v0, v1, std::forward<F>(f));
|
449
|
+
}
|
450
|
+
}
|
451
|
+
else if (v1.template is<T>())
|
452
|
+
{
|
453
|
+
return binary_dispatcher_lhs<F, V, R, T, Types...>::apply_const(v0, v1, std::forward<F>(f));
|
454
|
+
}
|
455
|
+
return binary_dispatcher<F, V, R, Types...>::apply_const(v0, v1, std::forward<F>(f));
|
456
|
+
}
|
457
|
+
|
458
|
+
VARIANT_INLINE static R apply(V& v0, V& v1, F&& f)
|
459
|
+
{
|
460
|
+
if (v0.template is<T>())
|
461
|
+
{
|
462
|
+
if (v1.template is<T>())
|
463
|
+
{
|
464
|
+
return f(unwrapper<T>::apply(v0.template get_unchecked<T>()),
|
465
|
+
unwrapper<T>::apply(v1.template get_unchecked<T>())); // call binary functor
|
466
|
+
}
|
467
|
+
else
|
468
|
+
{
|
469
|
+
return binary_dispatcher_rhs<F, V, R, T, Types...>::apply(v0, v1, std::forward<F>(f));
|
470
|
+
}
|
471
|
+
}
|
472
|
+
else if (v1.template is<T>())
|
473
|
+
{
|
474
|
+
return binary_dispatcher_lhs<F, V, R, T, Types...>::apply(v0, v1, std::forward<F>(f));
|
475
|
+
}
|
476
|
+
return binary_dispatcher<F, V, R, Types...>::apply(v0, v1, std::forward<F>(f));
|
477
|
+
}
|
478
|
+
};
|
479
|
+
|
480
|
+
template <typename F, typename V, typename R, typename T>
|
481
|
+
struct binary_dispatcher<F, V, R, T>
|
482
|
+
{
|
483
|
+
VARIANT_INLINE static R apply_const(V const& v0, V const& v1, F&& f)
|
484
|
+
{
|
485
|
+
return f(unwrapper<T>::apply_const(v0.template get_unchecked<T>()),
|
486
|
+
unwrapper<T>::apply_const(v1.template get_unchecked<T>())); // call binary functor
|
487
|
+
}
|
488
|
+
|
489
|
+
VARIANT_INLINE static R apply(V& v0, V& v1, F&& f)
|
490
|
+
{
|
491
|
+
return f(unwrapper<T>::apply(v0.template get_unchecked<T>()),
|
492
|
+
unwrapper<T>::apply(v1.template get_unchecked<T>())); // call binary functor
|
493
|
+
}
|
494
|
+
};
|
495
|
+
|
496
|
+
// comparator functors
|
497
|
+
struct equal_comp
|
498
|
+
{
|
499
|
+
template <typename T>
|
500
|
+
bool operator()(T const& lhs, T const& rhs) const
|
501
|
+
{
|
502
|
+
return lhs == rhs;
|
503
|
+
}
|
504
|
+
};
|
505
|
+
|
506
|
+
struct less_comp
|
507
|
+
{
|
508
|
+
template <typename T>
|
509
|
+
bool operator()(T const& lhs, T const& rhs) const
|
510
|
+
{
|
511
|
+
return lhs < rhs;
|
512
|
+
}
|
513
|
+
};
|
514
|
+
|
515
|
+
template <typename Variant, typename Comp>
|
516
|
+
class comparer
|
517
|
+
{
|
518
|
+
public:
|
519
|
+
explicit comparer(Variant const& lhs) noexcept
|
520
|
+
: lhs_(lhs) {}
|
521
|
+
comparer& operator=(comparer const&) = delete;
|
522
|
+
// visitor
|
523
|
+
template <typename T>
|
524
|
+
bool operator()(T const& rhs_content) const
|
525
|
+
{
|
526
|
+
T const& lhs_content = lhs_.template get_unchecked<T>();
|
527
|
+
return Comp()(lhs_content, rhs_content);
|
528
|
+
}
|
529
|
+
|
530
|
+
private:
|
531
|
+
Variant const& lhs_;
|
532
|
+
};
|
533
|
+
|
534
|
+
} // namespace detail
|
535
|
+
|
536
|
+
struct no_init
|
537
|
+
{
|
538
|
+
};
|
539
|
+
|
540
|
+
template <typename... Types>
|
541
|
+
class variant
|
542
|
+
{
|
543
|
+
static_assert(sizeof...(Types) > 0, "Template parameter type list of variant can not be empty");
|
544
|
+
static_assert(!detail::disjunction<std::is_reference<Types>...>::value, "Variant can not hold reference types. Maybe use std::reference_wrapper?");
|
545
|
+
|
546
|
+
private:
|
547
|
+
static const std::size_t data_size = detail::static_max<sizeof(Types)...>::value;
|
548
|
+
static const std::size_t data_align = detail::static_max<alignof(Types)...>::value;
|
549
|
+
public:
|
550
|
+
struct adapted_variant_tag;
|
551
|
+
using types = std::tuple<Types...>;
|
552
|
+
private:
|
553
|
+
using first_type = typename std::tuple_element<0, types>::type;
|
554
|
+
using data_type = typename std::aligned_storage<data_size, data_align>::type;
|
555
|
+
using helper_type = detail::variant_helper<Types...>;
|
556
|
+
|
557
|
+
std::size_t type_index;
|
558
|
+
data_type data;
|
559
|
+
|
560
|
+
public:
|
561
|
+
VARIANT_INLINE variant() noexcept(std::is_nothrow_default_constructible<first_type>::value)
|
562
|
+
: type_index(sizeof...(Types)-1)
|
563
|
+
{
|
564
|
+
static_assert(std::is_default_constructible<first_type>::value, "First type in variant must be default constructible to allow default construction of variant");
|
565
|
+
new (&data) first_type();
|
566
|
+
}
|
567
|
+
|
568
|
+
VARIANT_INLINE variant(no_init) noexcept
|
569
|
+
: type_index(detail::invalid_value) {}
|
570
|
+
|
571
|
+
// http://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers
|
572
|
+
template <typename T, typename Traits = detail::value_traits<T, Types...>,
|
573
|
+
typename Enable = typename std::enable_if<Traits::is_valid && !std::is_same<variant<Types...>, typename Traits::value_type>::value>::type >
|
574
|
+
VARIANT_INLINE variant(T&& val) noexcept(std::is_nothrow_constructible<typename Traits::target_type, T&&>::value)
|
575
|
+
: type_index(Traits::index)
|
576
|
+
{
|
577
|
+
new (&data) typename Traits::target_type(std::forward<T>(val));
|
578
|
+
}
|
579
|
+
|
580
|
+
VARIANT_INLINE variant(variant<Types...> const& old)
|
581
|
+
: type_index(old.type_index)
|
582
|
+
{
|
583
|
+
helper_type::copy(old.type_index, &old.data, &data);
|
584
|
+
}
|
585
|
+
|
586
|
+
VARIANT_INLINE variant(variant<Types...>&& old) noexcept(std::is_nothrow_move_constructible<types>::value)
|
587
|
+
: type_index(old.type_index)
|
588
|
+
{
|
589
|
+
helper_type::move(old.type_index, &old.data, &data);
|
590
|
+
}
|
591
|
+
|
592
|
+
private:
|
593
|
+
VARIANT_INLINE void copy_assign(variant<Types...> const& rhs)
|
594
|
+
{
|
595
|
+
helper_type::destroy(type_index, &data);
|
596
|
+
type_index = detail::invalid_value;
|
597
|
+
helper_type::copy(rhs.type_index, &rhs.data, &data);
|
598
|
+
type_index = rhs.type_index;
|
599
|
+
}
|
600
|
+
|
601
|
+
VARIANT_INLINE void move_assign(variant<Types...>&& rhs)
|
602
|
+
{
|
603
|
+
helper_type::destroy(type_index, &data);
|
604
|
+
type_index = detail::invalid_value;
|
605
|
+
helper_type::move(rhs.type_index, &rhs.data, &data);
|
606
|
+
type_index = rhs.type_index;
|
607
|
+
}
|
608
|
+
|
609
|
+
public:
|
610
|
+
VARIANT_INLINE variant<Types...>& operator=(variant<Types...>&& other)
|
611
|
+
{
|
612
|
+
move_assign(std::move(other));
|
613
|
+
return *this;
|
614
|
+
}
|
615
|
+
|
616
|
+
VARIANT_INLINE variant<Types...>& operator=(variant<Types...> const& other)
|
617
|
+
{
|
618
|
+
copy_assign(other);
|
619
|
+
return *this;
|
620
|
+
}
|
621
|
+
|
622
|
+
// conversions
|
623
|
+
// move-assign
|
624
|
+
template <typename T>
|
625
|
+
VARIANT_INLINE variant<Types...>& operator=(T&& rhs) noexcept
|
626
|
+
{
|
627
|
+
variant<Types...> temp(std::forward<T>(rhs));
|
628
|
+
move_assign(std::move(temp));
|
629
|
+
return *this;
|
630
|
+
}
|
631
|
+
|
632
|
+
// copy-assign
|
633
|
+
template <typename T>
|
634
|
+
VARIANT_INLINE variant<Types...>& operator=(T const& rhs)
|
635
|
+
{
|
636
|
+
variant<Types...> temp(rhs);
|
637
|
+
copy_assign(temp);
|
638
|
+
return *this;
|
639
|
+
}
|
640
|
+
|
641
|
+
template <typename T, typename std::enable_if<
|
642
|
+
(detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
|
643
|
+
VARIANT_INLINE bool is() const
|
644
|
+
{
|
645
|
+
return type_index == detail::direct_type<T, Types...>::index;
|
646
|
+
}
|
647
|
+
|
648
|
+
template <typename T,typename std::enable_if<
|
649
|
+
(detail::direct_type<recursive_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
|
650
|
+
VARIANT_INLINE bool is() const
|
651
|
+
{
|
652
|
+
return type_index == detail::direct_type<recursive_wrapper<T>, Types...>::index;
|
653
|
+
}
|
654
|
+
|
655
|
+
VARIANT_INLINE bool valid() const
|
656
|
+
{
|
657
|
+
return type_index != detail::invalid_value;
|
658
|
+
}
|
659
|
+
|
660
|
+
template <typename T, typename... Args>
|
661
|
+
VARIANT_INLINE void set(Args&&... args)
|
662
|
+
{
|
663
|
+
helper_type::destroy(type_index, &data);
|
664
|
+
type_index = detail::invalid_value;
|
665
|
+
new (&data) T(std::forward<Args>(args)...);
|
666
|
+
type_index = detail::direct_type<T, Types...>::index;
|
667
|
+
}
|
668
|
+
|
669
|
+
// get_unchecked<T>()
|
670
|
+
template <typename T, typename std::enable_if<
|
671
|
+
(detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
|
672
|
+
VARIANT_INLINE T& get_unchecked()
|
673
|
+
{
|
674
|
+
return *reinterpret_cast<T*>(&data);
|
675
|
+
}
|
676
|
+
|
677
|
+
#ifdef HAS_EXCEPTIONS
|
678
|
+
// get<T>()
|
679
|
+
template <typename T, typename std::enable_if<
|
680
|
+
(detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
|
681
|
+
VARIANT_INLINE T& get()
|
682
|
+
{
|
683
|
+
if (type_index == detail::direct_type<T, Types...>::index)
|
684
|
+
{
|
685
|
+
return *reinterpret_cast<T*>(&data);
|
686
|
+
}
|
687
|
+
else
|
688
|
+
{
|
689
|
+
throw bad_variant_access("in get<T>()");
|
690
|
+
}
|
691
|
+
}
|
692
|
+
#endif
|
693
|
+
|
694
|
+
template <typename T, typename std::enable_if<
|
695
|
+
(detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
|
696
|
+
VARIANT_INLINE T const& get_unchecked() const
|
697
|
+
{
|
698
|
+
return *reinterpret_cast<T const*>(&data);
|
699
|
+
}
|
700
|
+
|
701
|
+
#ifdef HAS_EXCEPTIONS
|
702
|
+
template <typename T, typename std::enable_if<
|
703
|
+
(detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
|
704
|
+
VARIANT_INLINE T const& get() const
|
705
|
+
{
|
706
|
+
if (type_index == detail::direct_type<T, Types...>::index)
|
707
|
+
{
|
708
|
+
return *reinterpret_cast<T const*>(&data);
|
709
|
+
}
|
710
|
+
else
|
711
|
+
{
|
712
|
+
throw bad_variant_access("in get<T>()");
|
713
|
+
}
|
714
|
+
}
|
715
|
+
#endif
|
716
|
+
|
717
|
+
// get_unchecked<T>() - T stored as recursive_wrapper<T>
|
718
|
+
template <typename T, typename std::enable_if<
|
719
|
+
(detail::direct_type<recursive_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
|
720
|
+
VARIANT_INLINE T& get_unchecked()
|
721
|
+
{
|
722
|
+
return (*reinterpret_cast<recursive_wrapper<T>*>(&data)).get();
|
723
|
+
}
|
724
|
+
|
725
|
+
#ifdef HAS_EXCEPTIONS
|
726
|
+
// get<T>() - T stored as recursive_wrapper<T>
|
727
|
+
template <typename T, typename std::enable_if<
|
728
|
+
(detail::direct_type<recursive_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
|
729
|
+
VARIANT_INLINE T& get()
|
730
|
+
{
|
731
|
+
if (type_index == detail::direct_type<recursive_wrapper<T>, Types...>::index)
|
732
|
+
{
|
733
|
+
return (*reinterpret_cast<recursive_wrapper<T>*>(&data)).get();
|
734
|
+
}
|
735
|
+
else
|
736
|
+
{
|
737
|
+
throw bad_variant_access("in get<T>()");
|
738
|
+
}
|
739
|
+
}
|
740
|
+
#endif
|
741
|
+
|
742
|
+
template <typename T, typename std::enable_if<
|
743
|
+
(detail::direct_type<recursive_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
|
744
|
+
VARIANT_INLINE T const& get_unchecked() const
|
745
|
+
{
|
746
|
+
return (*reinterpret_cast<recursive_wrapper<T> const*>(&data)).get();
|
747
|
+
}
|
748
|
+
|
749
|
+
#ifdef HAS_EXCEPTIONS
|
750
|
+
template <typename T, typename std::enable_if<
|
751
|
+
(detail::direct_type<recursive_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
|
752
|
+
VARIANT_INLINE T const& get() const
|
753
|
+
{
|
754
|
+
if (type_index == detail::direct_type<recursive_wrapper<T>, Types...>::index)
|
755
|
+
{
|
756
|
+
return (*reinterpret_cast<recursive_wrapper<T> const*>(&data)).get();
|
757
|
+
}
|
758
|
+
else
|
759
|
+
{
|
760
|
+
throw bad_variant_access("in get<T>()");
|
761
|
+
}
|
762
|
+
}
|
763
|
+
#endif
|
764
|
+
|
765
|
+
// get_unchecked<T>() - T stored as std::reference_wrapper<T>
|
766
|
+
template <typename T, typename std::enable_if<
|
767
|
+
(detail::direct_type<std::reference_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
|
768
|
+
VARIANT_INLINE T& get_unchecked()
|
769
|
+
{
|
770
|
+
return (*reinterpret_cast<std::reference_wrapper<T>*>(&data)).get();
|
771
|
+
}
|
772
|
+
|
773
|
+
#ifdef HAS_EXCEPTIONS
|
774
|
+
// get<T>() - T stored as std::reference_wrapper<T>
|
775
|
+
template <typename T, typename std::enable_if<
|
776
|
+
(detail::direct_type<std::reference_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
|
777
|
+
VARIANT_INLINE T& get()
|
778
|
+
{
|
779
|
+
if (type_index == detail::direct_type<std::reference_wrapper<T>, Types...>::index)
|
780
|
+
{
|
781
|
+
return (*reinterpret_cast<std::reference_wrapper<T>*>(&data)).get();
|
782
|
+
}
|
783
|
+
else
|
784
|
+
{
|
785
|
+
throw bad_variant_access("in get<T>()");
|
786
|
+
}
|
787
|
+
}
|
788
|
+
#endif
|
789
|
+
|
790
|
+
template <typename T, typename std::enable_if<
|
791
|
+
(detail::direct_type<std::reference_wrapper<T const>, Types...>::index != detail::invalid_value)>::type* = nullptr>
|
792
|
+
VARIANT_INLINE T const& get_unchecked() const
|
793
|
+
{
|
794
|
+
return (*reinterpret_cast<std::reference_wrapper<T const> const*>(&data)).get();
|
795
|
+
}
|
796
|
+
|
797
|
+
#ifdef HAS_EXCEPTIONS
|
798
|
+
template <typename T, typename std::enable_if<
|
799
|
+
(detail::direct_type<std::reference_wrapper<T const>, Types...>::index != detail::invalid_value)>::type* = nullptr>
|
800
|
+
VARIANT_INLINE T const& get() const
|
801
|
+
{
|
802
|
+
if (type_index == detail::direct_type<std::reference_wrapper<T const>, Types...>::index)
|
803
|
+
{
|
804
|
+
return (*reinterpret_cast<std::reference_wrapper<T const> const*>(&data)).get();
|
805
|
+
}
|
806
|
+
else
|
807
|
+
{
|
808
|
+
throw bad_variant_access("in get<T>()");
|
809
|
+
}
|
810
|
+
}
|
811
|
+
#endif
|
812
|
+
|
813
|
+
// This function is deprecated because it returns an internal index field.
|
814
|
+
// Use which() instead.
|
815
|
+
MAPBOX_VARIANT_DEPRECATED VARIANT_INLINE std::size_t get_type_index() const
|
816
|
+
{
|
817
|
+
return type_index;
|
818
|
+
}
|
819
|
+
|
820
|
+
VARIANT_INLINE int which() const noexcept
|
821
|
+
{
|
822
|
+
return static_cast<int>(sizeof...(Types)-type_index - 1);
|
823
|
+
}
|
824
|
+
|
825
|
+
template <typename T, typename std::enable_if<
|
826
|
+
(detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
|
827
|
+
VARIANT_INLINE static constexpr int which() noexcept
|
828
|
+
{
|
829
|
+
return static_cast<int>(sizeof...(Types)-detail::direct_type<T, Types...>::index - 1);
|
830
|
+
}
|
831
|
+
|
832
|
+
// visitor
|
833
|
+
// unary
|
834
|
+
template <typename F, typename V, typename R = typename detail::result_of_unary_visit<F, first_type>::type>
|
835
|
+
auto VARIANT_INLINE static visit(V const& v, F&& f)
|
836
|
+
-> decltype(detail::dispatcher<F, V, R, Types...>::apply_const(v, std::forward<F>(f)))
|
837
|
+
{
|
838
|
+
return detail::dispatcher<F, V, R, Types...>::apply_const(v, std::forward<F>(f));
|
839
|
+
}
|
840
|
+
// non-const
|
841
|
+
template <typename F, typename V, typename R = typename detail::result_of_unary_visit<F, first_type>::type>
|
842
|
+
auto VARIANT_INLINE static visit(V& v, F&& f)
|
843
|
+
-> decltype(detail::dispatcher<F, V, R, Types...>::apply(v, std::forward<F>(f)))
|
844
|
+
{
|
845
|
+
return detail::dispatcher<F, V, R, Types...>::apply(v, std::forward<F>(f));
|
846
|
+
}
|
847
|
+
|
848
|
+
// binary
|
849
|
+
// const
|
850
|
+
template <typename F, typename V, typename R = typename detail::result_of_binary_visit<F, first_type>::type>
|
851
|
+
auto VARIANT_INLINE static binary_visit(V const& v0, V const& v1, F&& f)
|
852
|
+
-> decltype(detail::binary_dispatcher<F, V, R, Types...>::apply_const(v0, v1, std::forward<F>(f)))
|
853
|
+
{
|
854
|
+
return detail::binary_dispatcher<F, V, R, Types...>::apply_const(v0, v1, std::forward<F>(f));
|
855
|
+
}
|
856
|
+
// non-const
|
857
|
+
template <typename F, typename V, typename R = typename detail::result_of_binary_visit<F, first_type>::type>
|
858
|
+
auto VARIANT_INLINE static binary_visit(V& v0, V& v1, F&& f)
|
859
|
+
-> decltype(detail::binary_dispatcher<F, V, R, Types...>::apply(v0, v1, std::forward<F>(f)))
|
860
|
+
{
|
861
|
+
return detail::binary_dispatcher<F, V, R, Types...>::apply(v0, v1, std::forward<F>(f));
|
862
|
+
}
|
863
|
+
|
864
|
+
~variant() noexcept // no-throw destructor
|
865
|
+
{
|
866
|
+
helper_type::destroy(type_index, &data);
|
867
|
+
}
|
868
|
+
|
869
|
+
// comparison operators
|
870
|
+
// equality
|
871
|
+
VARIANT_INLINE bool operator==(variant const& rhs) const
|
872
|
+
{
|
873
|
+
assert(valid() && rhs.valid());
|
874
|
+
if (this->which() != rhs.which())
|
875
|
+
{
|
876
|
+
return false;
|
877
|
+
}
|
878
|
+
detail::comparer<variant, detail::equal_comp> visitor(*this);
|
879
|
+
return visit(rhs, visitor);
|
880
|
+
}
|
881
|
+
|
882
|
+
VARIANT_INLINE bool operator!=(variant const& rhs) const
|
883
|
+
{
|
884
|
+
return !(*this == rhs);
|
885
|
+
}
|
886
|
+
|
887
|
+
// less than
|
888
|
+
VARIANT_INLINE bool operator<(variant const& rhs) const
|
889
|
+
{
|
890
|
+
assert(valid() && rhs.valid());
|
891
|
+
if (this->which() != rhs.which())
|
892
|
+
{
|
893
|
+
return this->which() < rhs.which();
|
894
|
+
}
|
895
|
+
detail::comparer<variant, detail::less_comp> visitor(*this);
|
896
|
+
return visit(rhs, visitor);
|
897
|
+
}
|
898
|
+
VARIANT_INLINE bool operator>(variant const& rhs) const
|
899
|
+
{
|
900
|
+
return rhs < *this;
|
901
|
+
}
|
902
|
+
VARIANT_INLINE bool operator<=(variant const& rhs) const
|
903
|
+
{
|
904
|
+
return !(*this > rhs);
|
905
|
+
}
|
906
|
+
VARIANT_INLINE bool operator>=(variant const& rhs) const
|
907
|
+
{
|
908
|
+
return !(*this < rhs);
|
909
|
+
}
|
910
|
+
};
|
911
|
+
|
912
|
+
// unary visitor interface
|
913
|
+
// const
|
914
|
+
template <typename F, typename V>
|
915
|
+
auto VARIANT_INLINE apply_visitor(F&& f, V const& v) -> decltype(V::visit(v, std::forward<F>(f)))
|
916
|
+
{
|
917
|
+
return V::visit(v, std::forward<F>(f));
|
918
|
+
}
|
919
|
+
|
920
|
+
// non-const
|
921
|
+
template <typename F, typename V>
|
922
|
+
auto VARIANT_INLINE apply_visitor(F&& f, V& v) -> decltype(V::visit(v, std::forward<F>(f)))
|
923
|
+
{
|
924
|
+
return V::visit(v, std::forward<F>(f));
|
925
|
+
}
|
926
|
+
|
927
|
+
// binary visitor interface
|
928
|
+
// const
|
929
|
+
template <typename F, typename V>
|
930
|
+
auto VARIANT_INLINE apply_visitor(F&& f, V const& v0, V const& v1) -> decltype(V::binary_visit(v0, v1, std::forward<F>(f)))
|
931
|
+
{
|
932
|
+
return V::binary_visit(v0, v1, std::forward<F>(f));
|
933
|
+
}
|
934
|
+
|
935
|
+
// non-const
|
936
|
+
template <typename F, typename V>
|
937
|
+
auto VARIANT_INLINE apply_visitor(F&& f, V& v0, V& v1) -> decltype(V::binary_visit(v0, v1, std::forward<F>(f)))
|
938
|
+
{
|
939
|
+
return V::binary_visit(v0, v1, std::forward<F>(f));
|
940
|
+
}
|
941
|
+
|
942
|
+
// getter interface
|
943
|
+
|
944
|
+
#ifdef HAS_EXCEPTIONS
|
945
|
+
template <typename ResultType, typename T>
|
946
|
+
auto get(T& var)->decltype(var.template get<ResultType>())
|
947
|
+
{
|
948
|
+
return var.template get<ResultType>();
|
949
|
+
}
|
950
|
+
#endif
|
951
|
+
|
952
|
+
template <typename ResultType, typename T>
|
953
|
+
ResultType& get_unchecked(T& var)
|
954
|
+
{
|
955
|
+
return var.template get_unchecked<ResultType>();
|
956
|
+
}
|
957
|
+
|
958
|
+
#ifdef HAS_EXCEPTIONS
|
959
|
+
template <typename ResultType, typename T>
|
960
|
+
auto get(T const& var)->decltype(var.template get<ResultType>())
|
961
|
+
{
|
962
|
+
return var.template get<ResultType>();
|
963
|
+
}
|
964
|
+
#endif
|
965
|
+
|
966
|
+
template <typename ResultType, typename T>
|
967
|
+
ResultType const& get_unchecked(T const& var)
|
968
|
+
{
|
969
|
+
return var.template get_unchecked<ResultType>();
|
970
|
+
}
|
971
|
+
} // namespace util
|
972
|
+
} // namespace mapbox
|
973
|
+
|
974
|
+
#endif // MAPBOX_UTIL_VARIANT_HPP
|