-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpolyvar.hpp
77 lines (68 loc) · 2.62 KB
/
polyvar.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/*
Copyright 2016 Barrett Adair
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
#ifndef POLYVAR_HPP
#define POLYVAR_HPP
#include <boost/preprocessor/seq/seq.hpp>
#include <boost/preprocessor/seq/elem.hpp>
#include <boost/preprocessor/seq/size.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
#include <type_traits>
#define POLYVAR_USE_BOOST
//#define POLYVAR_USE_MAPBOX
#if defined POLYVAR_USE_BOOST
# include <boost/variant.hpp>
# define POLYVAR_VARIANT_IMPL boost::variant
# define POLYVAR_USING \
using POLYVAR_VARIANT_IMPL<Ts...>::variant; \
using POLYVAR_VARIANT_IMPL<Ts...>::operator=; \
using POLYVAR_VARIANT_IMPL<Ts...>::which; \
using POLYVAR_VARIANT_IMPL<Ts...>::empty; \
using POLYVAR_VARIANT_IMPL<Ts...>::type; \
/**/
# define POLYVAR_VISIT_IMPL boost::apply_visitor
#elif defined POLYVAR_USE_MAPBOX
// include it your damn self
# define POLYVAR_VARIANT_IMPL mapbox::util::variant
# define POLYVAR_VISIT_IMPL mapbox::util::apply_visitor
# define POLYVAR_USING \
using POLYVAR_VARIANT_IMPL<Ts...>::variant; \
using POLYVAR_VARIANT_IMPL<Ts...>::operator=; \
using POLYVAR_VARIANT_IMPL<Ts...>::which; \
using POLYVAR_VARIANT_IMPL<Ts...>::empty; \
using POLYVAR_VARIANT_IMPL<Ts...>::type; \
#else
# include <variant>
# define POLYVAR_VARIANT_IMPL std::variant
# define POLYVAR_VISIT_IMPL std::visit
// TODO - check these
# define POLYVAR_USING \
using POLYVAR_VARIANT_IMPL<Ts...>::variant; \
using POLYVAR_VARIANT_IMPL<Ts...>::operator=; \
using POLYVAR_VARIANT_IMPL<Ts...>::which; \
using POLYVAR_VARIANT_IMPL<Ts...>::empty; \
using POLYVAR_VARIANT_IMPL<Ts...>::type; \
/**/
#endif
#define DEFINE_POLYVAR(name, ...) \
template<typename... Ts> \
struct name : public POLYVAR_VARIANT_IMPL<Ts...> { \
\
using base = POLYVAR_VARIANT_IMPL<Ts...>; \
POLYVAR_USING \
\
BOOST_PP_REPEAT(BOOST_PP_SEQ_SIZE(__VA_ARGS__), POLYVAR_MEMFNS, __VA_ARGS__) \
} \
/**/
#define POLYVAR_MEMFNS(z, i, seq) POLYVAR_MEMFNS_I(BOOST_PP_SEQ_ELEM(i,seq))
#define POLYVAR_MEMFNS_I(name) \
template<typename... Args> \
constexpr decltype(auto) name(Args&&... args) { \
return POLYVAR_VISIT_IMPL([&](auto& v){ \
return v.name( \
static_cast<Args&&>(args)...);}, *this); \
} \
/**/
#endif // #ifndef POLYVAR_HPP