Skip to content

Instantly share code, notes, and snippets.

@deni64k
Last active January 28, 2019 14:58
Show Gist options
  • Save deni64k/2e118d8274df6d46d990ff2511152a16 to your computer and use it in GitHub Desktop.
Save deni64k/2e118d8274df6d46d990ff2511152a16 to your computer and use it in GitHub Desktop.
#include <iostream>
#include <sstream>
#include <string>
#include <tuple>
#include <array>
#include <experimental/array>
namespace std { using std::experimental::make_array; }
#include <boost/preprocessor.hpp>
#define EXPOSE_MEMBERS_Q(M_ignore0, M_ignore1, M_member) \
BOOST_PP_STRINGIZE(M_member)
#define EXPOSE_MEMBERS(...) \
auto members() { \
return std::forward_as_tuple(__VA_ARGS__); \
} \
auto members() const { \
return std::forward_as_tuple(__VA_ARGS__); \
} \
static constexpr auto names() { \
return std::make_array( \
BOOST_PP_LIST_ENUM( \
BOOST_PP_LIST_TRANSFORM( \
EXPOSE_MEMBERS_Q, @, \
BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__)))); \
}
template <typename T>
std::ostream& operator << (std::ostream& os, T const& obj) {
using std::operator <<;
std::apply([&os](auto const& names,
auto const& fst,
auto const&... rest) {
unsigned int i = 0;
os << names[i] << '=' << fst;
((os << ", " << names[++i] << '=' << rest), ...);
}, std::tuple_cat(std::make_tuple(obj.names()),
obj.members()));
return os;
}
template <typename T>
std::istream& operator >> (std::istream& is, T& obj) {
using std::operator >>;
std::apply([&is](auto&... members) {
(is >> ... >> members);
}, obj.members());
return is;
}
struct employee {
std::string name;
int salary;
EXPOSE_MEMBERS(name, salary);
};
int main(int, char**) {
employee e{"Steve Jobs", 1};
std::cout << e << std::endl;
std::string input = "Bill-Gates 100";
std::istringstream ss{input};
ss >> e;
std::cout << e << std::endl;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment