这个比较复杂,所以我自己无法解决。
下面是相关代码,后面我会更深入的解释。
#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;
- std::get/std::tuple_element 需要一个 constexpr 索引参数,所以我不能遍历元组类型。