sif*_*man 2 c++ inheritance templates shared-ptr stdvector
考虑以下:
#include <memory>
#include <utility>
#include <vector>
class Base
{
public:
Base()
: x(0)
{}
int x;
virtual ~Base() = default;
};
class Derived : public Base
{
public:
Derived(double z0)
: Base{}
, z{ z0 }
{}
double z;
};
template<class T> // T might be either a Base or a Derived class.
std::vector<std::shared_ptr<Base>> MakeVector(std::size_t numElements)
{
std::vector<std::shared_ptr<Base>> vec;
for(auto &i : numElements) { // Compiler error occurs here.
vec.push_back(std::make_shared<T>());
}
return vec;
}
class Foo
{
public:
Foo(std::size_t num_elements,
std::vector<std::shared_ptr<Base>> bars = {})
: m_bars{bars.empty() ? MakeVector<Base>(num_elements) : std::move(bars)}
{}
std::vector<std::shared_ptr<Base>> m_bars;
};
int main()
{
const std::size_t foo1Size = 4;
const std::size_t foo2Size = 5;
// Create a vector of shared_ptr to 4 Base objects:
Foo foo1 {foo1Size};
// Create a vector of shared_ptr to 5 Derived objects:
Foo foo2 {foo2Size, MakeVector<Derived>(foo2Size)};
}
Run Code Online (Sandbox Code Playgroud)
这里的目标是创建的请求数量Base或Derived对象,并填充std::vector与shared_ptrs到这些对象。
我在以下for语句中收到编译器错误:
错误:没有'begin'参数依赖模板参数,因此'begin'声明必须可用[-fpermissive]
如果我使用std::iteratorwith begin和end,不幸的是每个迭代器都无效push_back。无论如何,我都需要迭代特定的次数来填充向量。
这个问题有明显的解决方案吗?
您不能使用范围为基础的循环上std::size_t。你可以改变
for(auto &i : numElements) {
Run Code Online (Sandbox Code Playgroud)
至
for (std::size_t i = 0; i < numElements; i++) {
Run Code Online (Sandbox Code Playgroud)Derived没有默认的构造函数;您需要将参数传递给它进行构造,否则std::make_shared<T>()会失败。您可以MakeVector使用参数pack更改为以下内容:
template<class T, class... Types> // T might be either a Base or a Derived class.
std::vector<std::shared_ptr<Base>> MakeVector(std::size_t numElements, Types... args)
{
std::vector<std::shared_ptr<Base>> vec;
for (std::size_t i = 0; i < numElements; i++) {
vec.push_back(std::make_shared<T>(args...));
}
return vec;
}
Run Code Online (Sandbox Code Playgroud)
然后像
// Create a vector of shared_ptr to 5 Derived objects:
Foo foo2 {foo2Size, MakeVector<Derived>(foo2Size, 42)};
Run Code Online (Sandbox Code Playgroud)的numElements是一个std::size_t不具有类型begin和end迭代器定义,这是所需的(这是对于标准容器和用户定义的类型,而不是原始类型定义)基于范围的for循环。因此,您需要一个经典for循环
for(std::size_t index{ 0 }; index < numElements; index ++)
{
vec.push_back(std::make_shared<T>());
}
Run Code Online (Sandbox Code Playgroud)
或者只是一个while循环:
while(numElements--)
{
vec.push_back(std::make_shared<T>());
}
Run Code Online (Sandbox Code Playgroud)
其次,正如@songyuanyao指出的那样,Derived类必须具有default构造函数MakeVector才能起作用。您可以像这样默认一个:
Derived() = default;
// or
// Derived(double z0 = 0.0): Base{}, z{ z0 } {}
Run Code Online (Sandbox Code Playgroud)
或@songyuanyao的答案中最好的类似,为构造函数参数提供额外的varidic-template-args。