简体   繁体   English

c ++模板重构/泛化

[英]c++ template refactor/generalisation

Can this code be generalized so I can have a variable amount of types/arguments? 可以将此代码进行一般化,以便我可以使用不同数量的类型/参数吗?

(I really prefer to keep the functions out of the struct to keep the code more clean.) (我真的更喜欢将函数保留在结构之外,以使代码更干净。)

unsigned int const maxID = 2 ^ 8;
typedef unsigned int ID;

template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
struct SOA {
    T1 a1[maxID];
    T2 a2[maxID];
    T3 a3[maxID];
    T4 a4[maxID];
    T5 a5[maxID];
    T6 a6[maxID];
    ID currentMaxID = 0;
};

template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
ID AddEntity(SOA<T1, T2, T3, T4, T5, T6>& soa, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6) {
    soa.a1[soa.currentMaxID] = a1;
    soa.a2[soa.currentMaxID] = a2;
    soa.a3[soa.currentMaxID] = a3;
    soa.a4[soa.currentMaxID] = a4;
    soa.a5[soa.currentMaxID] = a5;
    soa.a6[soa.currentMaxID] = a6;
    return soa.currentMaxID++;
}

template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
ID RemoveEntity(SOA<T1, T2, T3, T4, T5, T6>& soa, ID entityID) {
    soa.currentMaxID--;
    soa.a1[entityID] = soa.a1[soa.currentMaxID];
    soa.a2[entityID] = soa.a2[soa.currentMaxID];
    soa.a3[entityID] = soa.a3[soa.currentMaxID];
    soa.a4[entityID] = soa.a4[soa.currentMaxID];
    soa.a5[entityID] = soa.a5[soa.currentMaxID];
    soa.a6[entityID] = soa.a6[soa.currentMaxID];
}

Yes. 是。

using ID = unsigned int;;
ID const maxID = 1<<8;

template <typename... Ts>
struct SOA {
  std::tuple< std::array< Ts, maxID >... > a;
  ID currentMaxID = 0;
};

Some boilerplate you don't need in C++14: ( std::decay_t and std::integral_sequence<unsigned replace them). 在C ++ 14中不需要的一些样板:( std::decay_tstd::integral_sequence<unsigned替换它们)。

template<unsigned...>struct indexes{using type=indexes;};
template<unsigned Max, unsigned...Is>struct make_indexes:make_indexes<Max-1,Max-1,Is...>{};
template<unsigned...Is>struct make_indexes<0,Is...>:indexes<Is...>{};
template<unsigned Max>using make_indexes_t=typename make_indexes<Max>::type;
template<class T>using decay_t=typename std::decay<T>::type;

Actual work. 实际工作。 First, helper details : 首先,助手details

namespace details {
  template <typename... Ts, unsigned... Is>
  ID AddEntity(indexes<Is...>, SOA<Ts...>& soa, decay_t<Ts> const&... ts) {
    int unused[] = { ( (std::get<Is>(soa.a)[soa.currentMaxID] = ts ), void(), 0 )..., 0 };
    (void)(unused); // just blocks warnings
    return soa.currentMaxID++;
  }
  template <typename... Ts, unsigned... Is>
  void RemoveEntity(indexes<Is...>, SOA<Ts...>& soa, ID entityID) {
    --soa.currentMaxID;
    int unused[] = {
      ( (std::get<Is>(soa.a)[entityId] = std::get<Is>(soa.a)[soa.currentMaxID] ),
      void(), 0 )..., 0
    };
    (void)(unused); // just blocks warnings
  }
}

which uses the array-to-do-many-things-trick. 它使用了阵列来做很多事情的技巧。 Then: 然后:

template <typename... Ts>
ID AddEntity(SOA<Ts...>& soa, decay_t<Ts> const&... ts) {
  return details::AddEntity( make_indexes_t< sizeof...(Ts) >{}, soa, ts... );
}

template <typename...Ts>
void RemoveEntity(SOA<Ts...>& soa, ID entityID) {
  details::RemoveEntity( make_indexes_t< sizeof...(Ts) >{}, soa, entityID );
}

or something like that (live example) . 或类似的东西(实时示例)

Note that I support the empty collection of Ts... . 请注意,我支持Ts...的空集合。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM