英文:
C++ Vector of shared_ptr of child to vector of shared_ptr to base
问题
I have this class:
class GameObjectTemplateModel : public DatabaseModel<GameObjectTemplate, WorldDatabaseConnection, GameObjectTemplateModel>;
And I have this:
std::vector<std::shared_ptr<DatabaseModel>> ManyWhere(const std::string& column, const std::string& where);
and this:
std::vector<std::shared_ptr<GameObjectTemplateModel>> LootableCollection;
Why I cannot do:
LootableCollection = ManyWhere("test","test");
My question is how can I make the vector of child shared_ptrs to get its data from the vector of base shared ptr?
Is it a good idea if I use dynamic_cast
?
英文:
I have this class
class GameObjectTemplateModel : public DatabaseModel<GameObjectTemplate, WorldDatabaseConnection, GameObjectTemplateModel>
And I have this:
std::vector<std::shared_ptr<DatabaseModel>> ManyWhere(const std::string& column, const std::string& where);
and this:
std::vector<std::shared_ptr<GameObjectTemplateModel>> LootableCollection;
Why I can not do:
LootableCollection = ManyWhere("test","test");
My question is how can I make the vector of child shared_ptrs to get it's data from vector of base shared ptr?
Is it good idea if I use dynamic_cast
?
答案1
得分: 1
Sure, here are the translated parts:
My question is how can I make the vector of child shared_ptrs to get its data from the vector of base shared ptr?
问题是如何使子 shared_ptr 的向量从基本 shared ptr 的向量中获取数据?
You need to have something that will convert each pointer in turn. In C++23 that can be a view like std::ranges::to<std::vector>
.
你需要有一些东西,依次转换每个指针。在C++23中,可以使用类似 std::ranges::to<std::vector>
的视图。
LootableCollection = ManyWhere("test","test") | std::ranges::tostd::vector;
LootableCollection = ManyWhere("test","test") | std::ranges::tostd::vector;
Prior to that you could use the iterator assignment (with a helper variable)
在那之前,您可以使用迭代器赋值(使用辅助变量)
auto collection = ManyWhere("test","test");
LootableCollection.assign(collection.begin(), collection.end());
auto collection = ManyWhere("test","test");
LootableCollection.assign(collection.begin(), collection.end());
Is it a good idea if I use dynamic_cast?
如果我使用 dynamic_cast 是一个好主意吗?
No. Using a pointer gotten via dynamic_cast is undefined behavior in almost all cases, and this isn't one of the exceptions.
不是的。几乎在所有情况下,使用通过 dynamic_cast 获取的指针都是未定义行为,而这不是其中的一个例外。
The type std::vector<std::shared_ptr<GameObjectTemplateModel>>
is not related to the type std::vector<std::shared_ptr<DatabaseModel>>
at all, despite the types GameObjectTemplateModel
and DatabaseModel
being related.
类型 std::vector<std::shared_ptr<GameObjectTemplateModel>>
与类型 std::vector<std::shared_ptr<DatabaseModel>>
完全无关,尽管类型 GameObjectTemplateModel
和 DatabaseModel
有关。
英文:
> My question is how can I make the vector of child shared_ptrs to get it's data from vector of base shared ptr?
You need to have something that will convert each pointer in turn. In C++23 that can be a view like std::ranges::to<std::vector>
.
LootableCollection = ManyWhere("test","test") | std::ranges::to<std::vector>;
Prior to that you could use the iterator assignment (with a helper variable)
auto collection = ManyWhere("test","test");
LootableCollection.assign(collection.begin(), collection.end());
> Is it good idea if I use dynamic_cast ?
No. Using a pointer gotten via dynamic_cast
is undefined behaviour in almost all cases, and this isn't one of the exceptions.
The type std::vector<std::shared_ptr<GameObjectTemplateModel>>
is not related to the type std::vector<std::shared_ptr<DatabaseModel>>
at all, despite the types GameObjectTemplateModel
and DatabaseModel
being related.
答案2
得分: 1
以下是您要翻译的内容:
问题在于,即使有一种方法可以在向量的元素类型之间进行转换,这并不会建立向量类型与赋值运算符/构造函数之间的关系,这些赋值/初始化所需的运算符/构造函数并不存在。
您需要为此提供自己的转换。取决于您是否确定元素的类型是否正确,您应该使用std::static_pointer_cast
或std::dynamic_pointer_cast
进行元素转换:
以下示例将Base
用作基类,Derived
用作派生类,以简化问题,并假设std::vector<std::shared_ptr<Base>>
的所有元素实际上引用Derived
。
struct Base
{
virtual ~Base() = default;
};
struct Derived : Base
{
};
template<class T, class U>
std::vector<std::shared_ptr<T>> ConvertSharedPointerVector(std::vector<std::shared_ptr<U>>&& from)
{
std::vector<std::shared_ptr<T>> to;
to.reserve(from.size());
for (auto& e : from)
{
to.emplace_back(std::static_pointer_cast<T>(std::move(e)));
}
return to;
}
std::vector<std::shared_ptr<Base>> Create()
{
return { std::make_shared<Derived>(), std::make_shared<Derived>() };
}
int main()
{
std::vector<std::shared_ptr<Derived>> convertedVector = ConvertSharedPointerVector<Derived>(Create());
}
注意:最好避免这种类型的转换。您可以尝试使用模板来处理这个问题。
英文:
The problem here is that even though there may be a way of converting between element types of the vectors, this doesn't establish a relationship between the vector types and the assigment operators/constructors necessary for the assignment/initialization to work do not exist.
You need to provide your own conversion for this. Depending on whether you're sure the types of the elements are ok or not, you should be using std::static_pointer_cast
or std::dynamic_pointer_cast
for the element conversions:
The following example uses Base
as base class and Derived
as derived class for simplicity and assumes all elements of the std::vector<std::shared_ptr<Base>>
actually reference Derived
s.
struct Base
{
virtual ~Base() = default;
};
struct Derived : Base
{
};
template<class T, class U>
std::vector<std::shared_ptr<T>> ConvertSharedPointerVector(std::vector<std::shared_ptr<U>>&& from)
{
std::vector<std::shared_ptr<T>> to;
to.reserve(from.size());
for (auto& e : from)
{
to.emplace_back(std::static_pointer_cast<T>(std::move(e)));
}
return to;
}
std::vector<std::shared_ptr<Base>> Create()
{
return { std::make_shared<Derived>(), std::make_shared<Derived>() };
}
int main()
{
std::vector<std::shared_ptr<Derived>> convertedVector = ConvertSharedPointerVector<Derived>(Create());
}
Note: You're likely better of avoiding this kind of conversion. You may be able to use templates for this.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论