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 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
| #include <iostream>
#include <string>
#include <stdexcept>
#include <boost/mpl/map.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/vector_c.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/has_key.hpp>
#include <boost/mpl/front.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/equal.hpp>
#include <boost/mpl/find_if.hpp>
#include <boost/type_traits.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/variant.hpp>
template<typename T>
struct reflection
{
};
template<typename T, typename Name, typename Args>
struct has_member
{
typedef typename boost::mpl::eval_if<
boost::mpl::has_key<
typename reflection<T>::type,
Name
>,
boost::mpl::find_if<
typename boost::mpl::at<
typename reflection<T>::type,
Name
>::type,
boost::mpl::bind<
boost::mpl::quote3<boost::mpl::equal>,
boost::mpl::bind<
boost::mpl::quote1<boost::mpl::second>,
boost::mpl::_1
>,
Args,
boost::is_convertible<
boost::mpl::_1,
boost::mpl::_2
>
>
>,
boost::mpl::void_
>::type iter;
static const bool value =
boost::mpl::eval_if<
boost::mpl::not_<
boost::is_same<
iter,
boost::mpl::void_
>
>,
boost::mpl::not_<
boost::is_same<
iter,
typename boost::mpl::end<
typename boost::mpl::at<
typename reflection<T>::type,
Name
>::type
>::type
>
>,
boost::mpl::false_
>::type::value;
typedef bool value_type;
typedef has_member<T, Name, Args> type;
typedef typename boost::mpl::eval_if<
boost::mpl::bool_<value>,
boost::mpl::first<
typename boost::mpl::deref<iter>::type
>,
boost::mpl::void_
>::type return_type;
};
template<>
struct reflection<std::string>
{
typedef boost::mpl::map<
boost::mpl::pair<
boost::mpl::vector_c<char, 'c', '_', 's', 't', 'r'>,
boost::mpl::vector<
boost::mpl::pair<
const char*,
boost::mpl::vector<>
>
>
>
> type;
};
template<>
struct reflection<int>
{
typedef boost::mpl::map<
> type;
};
typedef boost::variant<int, std::string> variant;
class visitor : public boost::static_visitor<variant>
{
public:
template<typename T>
typename boost::enable_if<
has_member<T, boost::mpl::vector_c<char, 'c', '_', 's', 't', 'r'>, boost::mpl::vector<> >,
variant
>::type
operator()(T& t) const
{
std::cout << t.c_str() << std::endl;
}
template<typename T>
typename boost::disable_if<
has_member<T, boost::mpl::vector_c<char, 'c', '_', 's', 't', 'r'>, boost::mpl::vector<> >,
variant
>::type
operator()(T& t) const
{
throw std::runtime_error("type " + std::string(typeid(T).name()) + " doesn't have c_str()");
}
};
int main()
{
variant u1 = std::string("hello");
variant u2 = 4;
boost::apply_visitor( visitor(), u1 ); // same as u1.c_str()
boost::apply_visitor( visitor(), u2 ); // same as u2.c_str()
} |
Partager