指向struct/class的递归成员的指针的变量序列作为模板参数

Man*_*ana 9 c++ templates template-meta-programming variadic-templates c++11

我正在努力进行一些模板编程,希望你能给我一些帮助.我编写了一个C++ 11接口,给出了一些结构,如:

struct Inner{
  double a;
};
struct Outer{
  double x, y, z, r;
  Inner in;
};
Run Code Online (Sandbox Code Playgroud)

对实际数据实现getter/setter,该数据是为指定的struct成员定制的:

MyData<Outer, double, &Outer::x,
                               &Outer::y, 
                               &Outer::z,
                               &Outer::in::a //This one is not working
              > state();

Outer foo = state.get();
//...  
state.set(foo);
Run Code Online (Sandbox Code Playgroud)

我设法通过以下方式为简单结构实现此功能:

template <typename T, typename U, U T::* ... Ms>
class MyData{
   std::vector<U *> var;
  public:
    explicit MyData();
    void set(T const& var_);
    T get() const;
};

template <typename T, typename U, U T::* ... Ms>
MyData<T, U, Ms ... >::Struct():var(sizeof...(Ms))
{
}

template <typename T, typename U, U T::* ... Ms>
void MyData<T, U, Ms ...>::set(T const& var_){
  unsigned i = 0;
  for ( auto&& d : {Ms ...} ){
    *var[i++] = var_.*d;
  }
}

template <typename T, typename U, U T::* ... Ms>
T MyData<T, U, Ms ...>::get() const{
  T var_;
  unsigned i = 0;
  for ( auto&& d : {Ms ...} ){
    var_.*d = *var[i++];
  }
  return var_;
}
Run Code Online (Sandbox Code Playgroud)

但是当我传递一个嵌套结构的成员时它失败了.理想情况下,我想实现一个指向成员类型的通用指针,它允许我与几个级别的范围分辨率兼容.我找到了这种方法,但我不确定这是否应该应用于我的问题或者是否存在一些可以使用的实现.提前致谢!

相关文章:

隐式模板参数

指向内部结构的指针

Jar*_*d42 7

您可以将成员指针包装到struct中以便更容易链接:

template <typename...> struct Accessor;

template <typename T, typename C, T (C::*m)>
struct Accessor<std::integral_constant<T (C::*), m>>
{
    const T& get(const C& c) { return c.*m; }
    T& get(C& c) { return c.*m; }
};

template <typename T, typename C, T (C::*m), typename ...Ts>
struct Accessor<std::integral_constant<T (C::*), m>, Ts...>
{
    auto get(const C& c) -> decltype(Accessor<Ts...>().get(c.*m))
    { return Accessor<Ts...>().get(c.*m); }

    auto get(C& c) -> decltype(Accessor<Ts...>().get(c.*m))
    { return Accessor<Ts...>().get(c.*m); }
};

template <typename T, typename U, typename ...Ts>
class MyData
{
    std::vector<U> vars{sizeof...(Ts)};

    template <std::size_t ... Is>
    T get(std::index_sequence<Is...>) const
    {
        T res;
        ((Ts{}.get(res) = vars[Is]), ...); // Fold expression C++17
        return res;
    }
    template <std::size_t ... Is>
    void set(std::index_sequence<Is...>, T const& t)
    {
        ((vars[Is] = Ts{}.get(t)), ...); // Fold expression C++17
    }

public:
    MyData() = default;

    T get() const { return get(std::index_sequence_for<Ts...>()); }
    void set(const T& t) { return set(std::index_sequence_for<Ts...>(), t); }

};
Run Code Online (Sandbox Code Playgroud)

与使用类似

template <auto ...ms> // C++17 too
using Member = Accessor<std::integral_constant<decltype(ms), ms>...>;

MyData<Outer, double, Member<&Outer::x>,
                           Member<&Outer::y>,
                           Member<&Outer::z>,
                           Member<&Outer::in, &Inner::a>
       > state;
Run Code Online (Sandbox Code Playgroud)

std::index_sequence是C++ 14,但可以在C++ 11中实现.
在C++ 11中也可以模拟来自C++ 17的折叠表达式.
typename <auto>(C++ 17)应该被替换typename <typename T, T value>.

演示