【发布时间】:2020-03-14 02:29:44
【问题描述】:
这个比较复杂,所以一直没能自己解决。
这里是相关代码,后面我会更深入的解释。
#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 索引参数,因此我无法遍历元组类型。
【问题讨论】:
-
此问题中显示的代码无法满足 stackoverflow.com 对 minimal reproducible example 的要求,这使得任何人几乎不可能自己尝试不同的方法以确保他们来提出一个可行的解决方案。这个问题必须是edited 以显示一个最小示例,不超过一两页代码(“最小”部分),任何人都可以剪切/粘贴、编译、运行和重现所描述的问题(“可重现”部分)完全如图所示。请参阅How to Ask 了解更多信息。
-
@SamVarshavchik 我编辑了代码以使其可重现:)
-
是否有理由使用
std::shared_ptr而不是std::unique_ptr与非拥有指针?据我所知,PropManager拥有Props,因此似乎没有任何理由共享所有权。另外,您能解释一下GetPropTuples的用途吗?我已经读了很多遍了,但我仍然不确定。我认为您正在寻找的可能是std::index_sequence。代码中有一些奇怪的东西。你能解释一下PropManager的用途吗?有了这些信息,有人可能能够设计出更简单的东西。 -
不同道具的数量不一致怎么办?例如,如果我们有 1 个
First、2 个Seconds 和 3 个Thirds,你会返回什么? -
@L.F.为了简单起见,我尝试不包含任何与确定哪些 prop 元组重叠相关的代码,但这应该不是问题
标签: c++ c++17 variadic-templates stdtuple fold-expression