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, class ...C, typename... T>
auto getMyField(const Obj& obj, T C::*... field)
{
return getField(obj, field...);
}
template <typename Obj, typename Out, class ...C, typename... T>
auto getMyField(const Obj& obj, 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 getMyField(obj, field...);
else
return getMyField(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. }
Aucun commentaire:
Enregistrer un commentaire