投射到未申报的类型

时间:2015-10-20 15:32:41

标签: templates c++11 std

这个想法与GetComponent() in Unity的通用版本相同。但我目前在以下模板问题上遇到了绊脚石:

template<class T> std::shared_ptr<T> MyClass::GetMyComponent()
{
    for (int i = 0; i < _baseTypeList.size(); i++)
    {
        auto base = _baseTypeList[i];
        T* check = dynamic_cast<T*>(base.get());
        if (check)
        {
            return std::static_pointer_cast<T>(base);
        }
    }
    return std::shared_ptr<T>(nullptr);
}

其中_baseTypeListstd::vector<std::shared_pntr{MyBaseType}>类型。

在这个函数中,我迭代一个组件列表,以查找是否有一个与我要求的类型相匹配的组件。如果有,则将组件强制转换为该类型。否则返回nullptr

但是,当我从外部代码调用此函数时,我收到以下错误:

error C2680: 'MyType*' : invalid target type for dynamic_cast

其中MyType是从组件派生的某个类。

当我将#include "MyType.h"放入标题时,它编译得很好但没有它就会出现此错误并且无法编译。

这意味着我不能在没有修改此模板类所在的头文件的情况下在其他类中使用它,这对我来说是个问题。

有没有一种方法可以实现类似的结果,而不必#include我在模板中传递的每个类型的标头?

[编辑] 为清楚起见,考虑一个人使用我的图书馆,他创建了一个类型 &#34; Foo:MyBaseType&#34;其中MyBaseType有一个虚拟方法&#34;更新&#34;这称为每一帧。 MyBaseType(包括Foo)类的任何实例都由此库管理,并且每帧都会调用更新。 因此,这个库有一个很大的&#34; MyBaseType&#34;对象。但是他们不知道它们的实际类型,只是它们来自&#34; MyBaseType&#34;,所以它可以调用它们上的Update()。

如果我需要特定类型,则库需要能够在此列表中搜索并返回它。 我希望这个&#34;搜索&#34;发生在图书馆本身,所以我不必公开列表,并写一个新的&#34;搜索&#34;从&#34; MyBaseType&#34;

派生的每种类型的方法

[FINAL] 事实证明我弄乱了项目中的包含顺序。 我试图做的最小例子是:

#include <stdio.h>
#include <tchar.h>
#include <iostream>
#include <memory>
#include "vector"

class MyBaseClass
{
    virtual void Update(){};
};

class MyLibrary
{
public:
    template<class T> std::shared_ptr<T> GetComponent();
    std::vector<std::shared_ptr<MyBaseClass>> list;
};

template<class T> std::shared_ptr<T> MyLibrary::GetComponent()
{
    static_assert(std::is_base_of<MyBaseClass, T>::value, "T1 is no subclass of ModelComponent");
    for (unsigned int i = 0; i < list.size(); i++)
    {
        auto comp = list[i];
        T* check = dynamic_cast<T*>(comp.get());
        if (check)
        {
            return std::static_pointer_cast<T>(comp);
        }
    }
    return std::shared_ptr<T>(nullptr);
}

class MyClass : public MyBaseClass
{
    void Update() override;
};

void MyClass::Update()
{

}

int _tmain(int argc, _TCHAR* argv[])
{
    MyLibrary lib;
    lib.list.push_back(std::make_shared<MyClass>());
    auto var = lib.GetComponent<MyClass>();
    std::cout << (var ? "var is object" : "var is not") << std::endl;

    while (true)
    {

    }
    return 0;
}

按预期工作。

主要问题是编译器在&#34; GetMyComponent&#34;功能,所以我找到了它的用法,按照建议做了一切。

但事实证明,第二种用法没有定义&#34; MyClass&#34;在调用之前(但没有给出错误,因为它是在头文件中向前声明的)。

1 个答案:

答案 0 :(得分:0)

您不需要在标题中包含可能的T类型的定义。您确实需要在扩展模板的翻译单元中定义的相关内容:

// client.cpp
#include <myclass.h>
#include <foo.h>  // defines class Foo

void f(MyClass *p)
{
    auto c = p->GetMyComponent<Foo>();
    c->foobar();
}