Skip to content

Instantly share code, notes, and snippets.

@nlyan
Created September 21, 2017 23:33
Show Gist options
  • Save nlyan/daf49e3d5226837822e3a161ab8b626e to your computer and use it in GitHub Desktop.
Save nlyan/daf49e3d5226837822e3a161ab8b626e to your computer and use it in GitHub Desktop.
#include <boost/mpl/at.hpp>
#include <boost/mpl/size.hpp>
#include <boost/variant/variant.hpp>
#include <type_traits>
namespace {
template <size_t N>
struct emplace_nth_helper {
template <typename Variant, typename Transform>
Variant
emplace (int const n, bool* const success, Transform&& transform) {
using type_vector = typename Variant::types;
using nth_type = typename boost::mpl::at_c<type_vector, N>::type;
if (n == N) {
*success = true;
return Variant (transform (nth_type ()));
} else {
return emplace_nth_helper<N - 1> ().template emplace<Variant> (
n, success, std::forward<Transform> (transform));
}
}
};
template <>
struct emplace_nth_helper<0> {
template <typename Variant, typename Transform>
Variant
emplace (int const n, bool* const success, Transform&& transform) {
using type_vector = typename Variant::types;
using nth_type = typename boost::mpl::at_c<type_vector, 0>::type;
if (n) {
*success = false;
return Variant ();
}
*success = true;
return Variant (transform (nth_type ()));
}
};
template <typename Variant, typename Transform>
inline Variant
emplace_nth (int n, bool* success, Transform&& transform) {
using type_vector = typename Variant::types;
auto const max = boost::mpl::size<type_vector>::value - 1;
if ((n < 0) || (n > max)) {
*success = false;
return Variant ();
}
emplace_nth_helper<boost::mpl::size<type_vector>::value - 1> next;
return next.template emplace<Variant> (
n, success, std::forward<Transform> (transform));
}
} // namespace
struct SomeOperation {
template <typename T>
T
operator() (T x) {
return x;
}
};
int
main (int argc, char** argv) {
bool success;
auto var = emplace_nth<boost::variant<int, float>> (
argc, &success, SomeOperation ());
return var.which ();
}
@nlyan
Copy link
Author

nlyan commented Sep 21, 2017

Result of g++ -std=c++14 -DNDEBUG -O3 variant.cpp under GCC 7.2.0

 510:	31 c0                	xor    %eax,%eax
 512:	83 ff 01             	cmp    $0x1,%edi
 515:	0f 94 c0             	sete   %al
 518:	c3                   	retq   
 519:	0f 1f 80 00 00 00 00 	nopl   0x0(%rax)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment