Skip to content

Instantly share code, notes, and snippets.

@pandaman64
Created April 1, 2013 13:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pandaman64/5284848 to your computer and use it in GitHub Desktop.
Save pandaman64/5284848 to your computer and use it in GitHub Desktop.
construct unnamed struct from tuple.
#include <type_traits>
#include <tuple>
#include <cstddef>
#include <string>
#include <iostream>
template<std::size_t ...Indices>
struct index_tuple{
constexpr index_tuple(){}
constexpr static index_tuple make(){
return {};
}
};
template<std::size_t N,typename Indices>
struct concat_index_tuple;
template<std::size_t N,std::size_t ...Indices>
struct concat_index_tuple<N,index_tuple<Indices...>>{
using type = index_tuple<N,Indices...>;
};
template<std::size_t Beg,std::size_t End>
struct make_index_tuple{
using type = typename concat_index_tuple<Beg,typename make_index_tuple<Beg + 1,End>::type>::type;
};
template<std::size_t End>
struct make_index_tuple<End,End>{
using type = index_tuple<End>;
};
template<typename Tuple>
using tuple_index = typename make_index_tuple<0,std::tuple_size<Tuple>::value - 1>::type;
template<std::size_t ...Indices,typename Tuple>
std::tuple<typename std::tuple_element<Indices,typename std::remove_reference<Tuple>::type>::type...>
pick(Tuple &&tuple){
return std::forward_as_tuple(std::get<Indices>(std::forward<Tuple>(tuple))...);
}
template<typename T,typename ...Args>
T construct(Args &&...args){
return { std::forward<Args>(args)... };
}
template<typename T,typename Tuple,std::size_t ...Indices>
T construct_from_tuple_unpack(Tuple &&tuple,index_tuple<Indices...>){
using std::get;
return construct<T>(get<Indices>(std::forward<Tuple>(tuple))...);
}
template<typename T,typename Tuple>
T construct_from_tuple(Tuple &&tuple){
return construct_from_tuple_unpack<T>(std::forward<Tuple>(tuple),tuple_index<typename std::decay<Tuple>::type>::make());
}
template<typename Tuple>
struct from_tuple_t{
using tuple_type = Tuple;
using tuple_ = typename std::remove_reference<tuple_type>::type;
using reference = tuple_&;
using rvalue_reference = tuple_&&;
tuple_type tuple;
from_tuple_t(reference t) : tuple(t){
}
from_tuple_t(rvalue_reference t) : tuple(std::move(t)){
}
template<typename T>
operator T(){
return construct_from_tuple<T>(std::forward<tuple_type>(tuple));
}
};
template<typename Tuple>
from_tuple_t<Tuple> from_tuple(Tuple &&args){
return { std::forward<Tuple>(args) };
}
enum class Sex{
Man,
Woman,
Undefined
};
std::ostream &operator <<(std::ostream &os,Sex sex){
switch(sex){
case Sex::Man:
os << "Man";
break;
case Sex::Woman:
os << "Woman";
break;
case Sex::Undefined:
os << "Undefined";
break;
}
return os;
}
std::tuple<char const*,int,Sex> func(){
return std::make_tuple("pandaman64",3,Sex::Undefined);
}
int main(){
struct{std::string name;int age;Sex sex;} const value = from_tuple(func());
std::cout << value.name << ',' << value.age << ',' << value.sex << std::endl;
struct{Sex sex;int age;} const picked = from_tuple(pick<2,1>(func()));
std::cout << picked.sex << ',' << picked.age << std::endl;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment