无法将派生的 class 存储在基数 classes 的指针向量中

Unable to store derived class in a vector of pointer of base classes

我有这个collection:

vector<unique_ptr<Light>>* lights;

我有很多Lightclass的后代,比如DirectionalLightPointLight等等。

我希望将 Light 的所有后代存储在 lights vector 中,如下所示:

template<typename T>
unique_ptr<T> CreateLight()
{
    static_assert(std::is_base_of<Light, T>::value, "Type must of descendant of type Light. ");
    unique_ptr<T> light(new T());
    lights->emplace_back(light);
    return light;
}

使用此方法的原因是我将我的灯光存储在 collection 中用于我的 renderer,这将发挥它的魔力使灯光影响着色器。

编辑

这些 collection 是名为 Scene 的 class 的一部分。我一直都需要它们,我需要将所有 Light 个实例放在堆上(连同 Scene class 拥有的所有其他实例)。 Renderer 的每一帧都会通过 collection 灯光来影响场景 objects' 着色器。在任何给定时间访问此向量至关重要。

我仍然需要引用场景中的灯光,以便我可以操纵它的属性。

错误信息是这样的:

Severity    Code    Description Project File    Line    Suppression State
Error   C2664   'std::unique_ptr<Light,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)': cannot convert argument 1 from 'std::unique_ptr<DirectionalLight,std::default_delete<_Ty>>' to 'std::nullptr_t'

这在构建期间失败,而不是运行时。 当然,我看了 this one 之类的答案,但无济于事。

我需要帮助来解决这个问题。

lights->emplace_back(light);

更改为:

lights->emplace_back(new T());

您可以简单地 return 引用新创建的对象:

std::vector<std::unique_ptr<Light>>* lights;

template<typename T, typename... Args>
T& CreateLight(Args&&... args)
{
    ...
    auto light = std::make_unique<T>(std::forward<Args>(args)...);
    lights->push_back(std::move(light));
    return *static_cast<T*>(lights->back().get());
}

编辑。阅读JeJo的答案后,修改CreateLight使其接受任何数字(包括零)构造 T.

的参数

I have many descendants of the Light class, like DirectionalLight, PointLight and so on. I wish to store all descendants of Light within that lights vector like so.

那么你只需要一个unique_ptr<Light>的向量而不是指向unique_ptr<Light>的向量的指针;这是一种过度设计的做事方式。

std::vector< std::unique_ptr<Light> > lights;

那你就可以轻松搞定了。

template<typename T>
void CreateLight()
{
   static_assert(std::is_base_of<Light, T>::value, "Type must of descendant of type Light. ");
   // store to vector directly
   lights.emplace_back( std::make_unique<T>(/*args*/));
}

how do I get the freshly created light instance so I can return it?

因为你在lights vector 的最后有新创建的实例,你可以直接在任何你想用的地方使用它。 See here

//Either directly
auto iter = lights.rbegin();
if(*iter) std::cout << "Done\n";

 // or
 auto lastElement = std::move(lights.back());
 if(lastElement) std::cout << "Done\n";