I am writing a method to extract values from arbitrarily nested structs. I am almost there, but would like to also provide an option to convert the value retrieved (by default no conversion). Since parameter packs can't be followed by another template parameter, I have to fudge this a bit. The below works except for the indicated line:
#include <iostream> #include <type_traits> typedef struct { int a; int b; } bar; typedef struct { int c; bar d; } baz; template <typename T, typename S, typename... Ss> auto inline getField(const T& obj, S field1, Ss... fields) { if constexpr (!sizeof...(fields)) return obj.*field1; else return getField(obj.*field1, fields...); } template <typename Obj, typename Out, class ...C, typename... T> auto inline getFieldC(const Obj& obj, Out, T C::*... field) { return static_cast<Out>(getField(obj, field...)); } template<class T> struct tag_t { using type = T; }; template<class...Ts> using last = typename std::tuple_element_t< sizeof...(Ts) - 1, std::tuple<tag_t<Ts>...> >::type; template <typename Obj, typename... T> auto getMyFieldWrapper(const Obj& obj, T... field) { if constexpr (std::is_member_object_pointer_v<last<Obj, T...>>) return getField(obj, field...); else return getFieldC(obj, last<Obj, T...>{}, field...); // <- this doesn't compile, need a way to pass all but last element of field } int main() { baz myObj; std::cout << getMyFieldWrapper(myObj, &baz::c); // works std::cout << getMyFieldWrapper(myObj, &baz::d, &bar::b); // works std::cout << getMyFieldWrapper(myObj, &baz::d, &bar::b, 0.); // doesn't work } How do I implement the indicated line? I'm using the latest MSVC, and am happy to make full use of C++17 to keep things short and simple.