Это довольно сложно, поэтому я не смог решить его самостоятельно.
Вот соответствующий код, я объясню подробнее позже.
#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, поэтому я не могу перебирать типы кортежей.
std::shared_ptr
вместоstd::unique_ptr
с указателями, не владеющими? Из того, что я могу сказать,PropManager
владеетProp
, поэтому, похоже, нет никаких причин для совместного владения. Кроме того, не могли бы вы объяснить, что должен делатьGetPropTuples
? Я читал это много раз, и я все еще не уверен. Я думаю, что вы ищете может бытьstd::index_sequence
. В коде есть странности. Не могли бы вы объяснить, для чегоPropManager
? Имея эту информацию, кто-то мог бы разработать что-то более простое. - person Indiana Kernick   schedule 14.03.2020First
, 2Second
и 3Third
? - person L. F.   schedule 14.03.2020