这是一个相当复杂的项目,所以我自己无法解决。
这是相关代码,我将在后面详细解释。
#include <memory>
#include <vector>
#include <tuple>
#include <typeinfo>
#include <iostream>
struct Prop
{
virtual ~Prop() {};
};
struct First : Prop
{
int a;
};
struct Second : Prop
{
int b;
};
struct Third : Prop
{
int c;
};
class PropManager
{
public:
template<typename PropType>
static std::shared_ptr<PropType> AddProp()
{
auto prop = std::make_shared<PropType>();
props.push_back(prop);
return prop;
}
static std::vector<std::shared_ptr<Prop>> props;
template <typename PropType>
static std::vector<std::shared_ptr<PropType>> GetProps()
{
std::vector<std::shared_ptr<PropType>> propTypes;
for (std::shared_ptr<Prop> prop : props)
{
if (!prop) continue;
if (typeid(PropType) == typeid( *prop.get() ) )
{
propTypes.push_back(std::static_pointer_cast<PropType>(prop));
}
}
return propTypes;
}
private:
template <typename NthPropType, typename ...RemainingPropTypes>
static void
RecurseFillPropTuples
(
std::vector<std::tuple<std::shared_ptr<NthPropType>, std::shared_ptr<RemainingPropTypes>... >>* tuples,
std::size_t recurse_count
)
{
auto props = GetProps<NthPropType>();
int i = 0;
for (std::shared_ptr<NthPropType> prop : props)
{
std::get<recurse_count>( (*tuples)[i] ) = prop;
i++;
}
if (sizeof...(RemainingPropTypes) > 0) {
RecurseFillPropTuples<RemainingPropTypes...>(tuples, recurse_count + 1);
}
}
public:
template <typename FirstPropType, typename ...NextPropTypes>
static std::vector<std::tuple<std::shared_ptr<FirstPropType>, std::shared_ptr<NextPropTypes>... >>*
GetPropTuples
(
std::vector<std::tuple<std::shared_ptr<FirstPropType>, std::shared_ptr<NextPropTypes>... >>* tuples = nullptr,
std::size_t recurse_count = 0
)
{
auto firstPropVector = GetProps<FirstPropType>();
tuples = new std::vector<std::tuple<std::shared_ptr<FirstPropType>, std::shared_ptr<NextPropTypes>... >>(firstPropVector.size());
int i = 0;
for (std::shared_ptr<FirstPropType> prop : firstPropVector)
{
std::get<0>((*tuples)[i]) = prop;
i++;
}
if (sizeof...(NextPropTypes) > 0)
{
PropManager::RecurseFillPropTuples<FirstPropType, NextPropTypes...>(tuples, recurse_count + 1);
}
return tuples;
}
};
std::vector<std::shared_ptr<Prop>> PropManager::props = {};
int main()
{
PropManager::AddProp<First>();
PropManager::AddProp<Second>();
PropManager::AddProp<Third>();
PropManager::GetPropTuples<First, Second, Third>();
}
最终,我的愿望是返回模板类型元组的向量。 实际上,这里有两个相关的问题。
PropManager::RecurseFillPropTuples<FirstPropType, NextPropTypes...>(tuples, recurse_count + 1);
std::get<recurse_count>( (*tuples)[i] ) = prop;
答案 0 :(得分:0)
第一点:如L.F.所述,您将在tuple
中分配的GetPropTuples()
的大小设置为FirstPropType
中props
的数目。如果以下类型的元素数更大怎么办?
auto firstPropVector = GetProps<FirstPropType>();
tuples = new std::vector<std::tuple<std::shared_ptr<FirstPropType>, std::shared_ptr<NextPropTypes>... >>(firstPropVector.size());
鉴于我尚未解决此问题,建议您避免递归,并且鉴于您已标记了C ++ 17,因此建议使用可折叠。
其他建议:尽可能使用auto
。
因此,给定一个设置值的辅助函数,给定类型和相应的索引
template <std::size_t I, typename PType, typename VType>
static void SetTuples (VType * pv)
{
std::size_t ind{};
for ( auto prop : GetProps<PType>() )
std::get<I>( (*pv)[ind++] ) = prop;
}
您基本上只需要一个索引序列,所以
template <typename ... PTypes, std::size_t ... Is>
static auto GetPropTuples (std::index_sequence<Is...>)
{
using RetType
= std::vector<std::tuple<std::shared_ptr<PTypes>...>>;
auto tuples = new RetType(1u); // <<--- set the correct size!!!
(SetTuples<Is, PTypes>(tuples), ...);
return tuples;
}
template <typename ... PTypes>
static auto GetPropTuples ()
{ return GetPropTuples<PTypes...>
(std::index_sequence_for<PTypes...>{}); }