集合中的智能指针多态性
Smart pointer polymorphism in collections
我正在尝试通过初始化列表初始化指向 class A
的指针集合。但是,初始化列表不能使用引用作为模板类型。
我有以下代码。
#include <iostream>
#include <functional>
#include <algorithm>
#include <vector>
#include <initializer_list>
#include <memory>
struct A
{
virtual void f() const noexcept { std::cout << "A"; }
};
struct B : public A
{
virtual void f() const noexcept override { std::cout << "B"; }
};
class Test
{
std::vector<std::shared_ptr<A>> vec;
public:
Test(const std::initializer_list<A>& list)
//Test(const std::initializer_list<A&>& list) <------ Solution?
{
for (auto& x : list)
vec.push_back(std::make_shared<A>(x));
}
void print()
{
std::for_each(vec.begin(), vec.end(), [](auto x) { x->f(); });
}
};
int main()
{
Test test = { A(), B() };
test.print();
}
代码打印:
AA
它应该打印:
AB
有没有一种简单的方法可以做到这一点,而不必在调用方法中创建指针?
相关文章(How do I implement polymorphism with std::shared_ptr?)对这个问题没有提供太多帮助。
您将在下一行shared_ptr
创建新的
vec.push_back(std::make_shared<A>(x));
x
是什么并不重要,您用它的值创建了一个新的 A
。
您可能想要创建一个 shared_ptr<A>
并将指针从 x.get()
传递到新的空 shared_ptr<A>
std::initializer_list<T>
按值保存传递的对象,所以不能存在多态。另外 std::make_shared<A>
总是创建一个 A
类型的对象,而不是从 A
派生的某种类型。你需要另一种方法。
由于您有任意数量的任意类型的参数,您可能需要一个可变参数模板构造函数。
编辑:我的代码建议太复杂了。 WhozCraig 的评论好多了:
template<class... Args>
Test(Args&&... args) :
vec { std::make_shared<std::remove_reference_t<Args>>(std::forward<Args>(args))... }
{
}
您正在使用 std::make_shared<A>()
插入向量。您正在将一堆 B
和 A
复制到一堆 A
.
如果您希望 main 中的语法起作用,最简单的方法是使用模板:
struct Foo {
template<typename... Args>
Foo(Args... args) :
vec{std::make_shared<Args>(std::move(args))...}
{}
private:
std::vector<std::shared_ptr<A>> vec;
};
我正在尝试通过初始化列表初始化指向 class A
的指针集合。但是,初始化列表不能使用引用作为模板类型。
我有以下代码。
#include <iostream>
#include <functional>
#include <algorithm>
#include <vector>
#include <initializer_list>
#include <memory>
struct A
{
virtual void f() const noexcept { std::cout << "A"; }
};
struct B : public A
{
virtual void f() const noexcept override { std::cout << "B"; }
};
class Test
{
std::vector<std::shared_ptr<A>> vec;
public:
Test(const std::initializer_list<A>& list)
//Test(const std::initializer_list<A&>& list) <------ Solution?
{
for (auto& x : list)
vec.push_back(std::make_shared<A>(x));
}
void print()
{
std::for_each(vec.begin(), vec.end(), [](auto x) { x->f(); });
}
};
int main()
{
Test test = { A(), B() };
test.print();
}
代码打印:
AA
它应该打印:
AB
有没有一种简单的方法可以做到这一点,而不必在调用方法中创建指针?
相关文章(How do I implement polymorphism with std::shared_ptr?)对这个问题没有提供太多帮助。
您将在下一行shared_ptr
创建新的
vec.push_back(std::make_shared<A>(x));
x
是什么并不重要,您用它的值创建了一个新的 A
。
您可能想要创建一个 shared_ptr<A>
并将指针从 x.get()
传递到新的空 shared_ptr<A>
std::initializer_list<T>
按值保存传递的对象,所以不能存在多态。另外 std::make_shared<A>
总是创建一个 A
类型的对象,而不是从 A
派生的某种类型。你需要另一种方法。
由于您有任意数量的任意类型的参数,您可能需要一个可变参数模板构造函数。
编辑:我的代码建议太复杂了。 WhozCraig 的评论好多了:
template<class... Args> Test(Args&&... args) : vec { std::make_shared<std::remove_reference_t<Args>>(std::forward<Args>(args))... } { }
您正在使用 std::make_shared<A>()
插入向量。您正在将一堆 B
和 A
复制到一堆 A
.
如果您希望 main 中的语法起作用,最简单的方法是使用模板:
struct Foo {
template<typename... Args>
Foo(Args... args) :
vec{std::make_shared<Args>(std::move(args))...}
{}
private:
std::vector<std::shared_ptr<A>> vec;
};