#include <exception> #include <iostream> #include <string> #include <tuple> #include <typeinfo>
// goal: make this code work with constexpr, tested on g++ 4.7.2 (-std=c++11) //#define constexpr std::string operator"" _s(const char *literal_string, size_t chars) { return std::string(literal_string, chars); } template <typename T,typename U> constexpr bool typematch(const T& a, const U& b) { return typeid(a) == typeid(b); } template <size_t N> struct MatchTypes_t { MatchTypes_t() = default; template<typename M,typename ...T> constexpr const void *matchType(const M& match, const std::tuple<T...>& t) const { const size_t tsize = std::tuple_size<std::tuple<T...>>::value; if (typematch(std::get<tsize-N>(t), match)) { constexpr auto find = MatchTypes_t<N-1>(); return find.matchType(match, t) ? nullptr : static_cast<const void*>(&(std::get<tsize-N>(t))); } else { constexpr auto find = MatchTypes_t<N-1>(); return find.matchType(match, t); } } }; template <> struct MatchTypes_t<0> { template<typename M,typename ...T> constexpr const void *matchType(const M& match, const std::tuple<T...>& t) const { return nullptr; } }; namespace std { template <typename M,typename ...T> const M& get(std::tuple<T...>& t, std::exception e = std::bad_typeid(), M dummy = M()) throw(std::exception) { const size_t tsize = std::tuple_size<std::tuple<T...>>::value; constexpr auto find = MatchTypes_t<tsize>(); constexpr const void *ptr = find.matchType(dummy, t); if (!ptr) { // static_assert(ptr, "bad_typeid or more than one of that type"); throw e; } return *(static_cast<const M*>(ptr)); } } // namespace std int main() { auto vary = std::make_tuple('A', "mixed set of"_s, -1.2, 2); const auto &s = std::get<std::string>(vary); const auto d = std::get<double>(vary); return ((s == "mixed set of") && (d == -1.2)) ? 0 : 1; }