Skip to content

Instantly share code, notes, and snippets.

@paosidufygthrj
Last active August 29, 2015 14:27
Show Gist options
  • Save paosidufygthrj/b2450e262beecf2ae664 to your computer and use it in GitHub Desktop.
Save paosidufygthrj/b2450e262beecf2ae664 to your computer and use it in GitHub Desktop.
[C++]variant 型に格納された値を異なる variant 型に格納できる場合はコピーする
#include <boost/variant.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/find.hpp>
#include <type_traits>
#include <iostream>
using namespace boost;
using namespace boost::mpl;
// variant が格納できる型に T 型が含まれているか返すメタ関数
template <typename T, typename V>
struct is_included_variant {
using types = typename V::types;
using itr = typename find<types, T>::type;
using last = typename end<types>::type;
static const bool value = !is_same<itr, last>::value;
};
// variant が T 型を格納可能ならパラメータの値をコピーするメタ関数
template <typename T, typename V, typename Ignore = void>
struct setter_if_included_variant {
static void set(V&, const T&) {}
};
template <typename T, typename V>
struct setter_if_included_variant<T, V, typename std::enable_if<is_included_variant<T, V>::value>::type> {
static void set(V& container, const T& value) {
container = value;
}
};
template <typename T, typename V>
inline void set_if_included_variant(V& container, const T& value) {
setter_if_included_variant<T, V>::set(container, value);
}
// variant V 型に格納された値を variant C 型に格納できる場合はコピーするメタ関数
template <typename C, typename V>
struct setter_if_included_variant2 {
struct functor {
C& container;
const V& value;
functor(C& container, const V& value)
: container(container), value(value)
{}
template <typename T>
void operator () (const T&) const {
if (value.type() == typeid(T)) {
set_if_included_variant(container, get<T>(value));
}
}
};
static void set(C& container, const V& value) {
functor f(container, value);
for_each<typename V::types>(f);
}
};
template <typename C, typename V>
void set_if_included_variant2(C& container, const V& value) {
setter_if_included_variant2<C, V>::set(container, value);
std::cout << "c:" << container << " v:" << value << std::endl;
}
int main() {
using type1 = variant<int, float>;
using type2 = variant<int, double>;
type1 c = 0;
set_if_included_variant2(c, type2(1)); // c:1 v:1
set_if_included_variant2(c, type2(2.0)); // c:1 v:2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment