模板功能搞砸了

时间:2012-04-16 11:50:44

标签: c++ function templates typeid typeinfo

所以我的ResourceManager类对于使用c ++的游戏有点问题。 所以我试图从我的常规addImage函数中创建一个模板函数,所以它也会添加声音,但我得到了一些我无法真正处理的错误你们可以帮帮我吗? :d

.HPP

#ifndef RESOURCE_MANAGER_HPP
#define RESOURCE_MANAGER_HPP

#include "Image.cpp"
#include "SoundBuffer.cpp"
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>

typedef std::map<std::string, sz::Image*> ImagesContainer;
typedef std::map<std::string, sz::Image*>::iterator ImagesContainerIt;
typedef std::map<std::string, sz::SoundBuffer*> SoundsContainer;
typedef std::map<std::string, sz::SoundBuffer*>::iterator SoundsContainerIt;
typedef std::map<std::string, sf::Music*> MusicContainer;
typedef std::map<std::string, sf::Music*>::iterator MusicContainerIt;

namespace sz
{
        //      meanwhile this class is only for images, need to edit later for
        //      it to be also able to load sounds, etc...
        class ResourceManager{
                private:
                ResourceManager() {};
                ResourceManager(ResourceManager const&) {};
                static ResourceManager *rm;
                // add functions and variables here
                ImagesContainer imagesContainer;
                SoundsContainer soundsContainer;
                MusicContainer  musicContainer;
                template <class type>
                void AddNew(std::string imagePath);

                public:
                static ResourceManager *Instance();
                // add functions here
                template <class type>
                type *Get(std::string imagePath);
        };
}

#endif

的.cpp

#include "ResourceManager.hpp"
#include <typeinfo>

namespace sz
{
        ResourceManager *ResourceManager::rm = NULL;  

        ResourceManager *ResourceManager::Instance()
        {
           if (!rm)
                  rm = new ResourceManager;

           return rm;
        }

        template <class type>
        void ResourceManager::AddNew(std::string filePath)
        {
                type *item = new type(filePath);
                if(typeid(type) == typeid(sz::Image))
                        imagesContainer[filePath] = item;
                else if(typeid(type) == typeid(sz::SoundBuffer))
                        soundsContainer[filePath] = item;
                else
                        return;
        }

        template <class type>
        type *ResourceManager::Get(std::string filePath)
        {
                if(typeid(type) == typeid(sz::Image))
                {
                        ImagesContainerIt it = imagesContainer.find(filePath);
                        if(it == imagesContainer.end())
                        {
                                AddNew<type>(filePath);
                        }
                        it = imagesContainer.find(filePath);
                        return it->second;
                }

                else if(typeid(type) == typeid(sz::SoundBuffer))
                {
                        SoundsContainerIt it = soundsContainer.find(filePath);
                        if(it == soundsContainer.end())
                        {
                                AddNew<type>(filePath);
                        }
                        it = soundsContainer.find(filePath);
                        return it->second;
                }

                else
                        return NULL;
        }
}

错误@ _ @

g++ -Wall -c "Sprite.cpp" (in directory: /home/gannash/Desktop/Open Heroes/Engine)
In file included from Sprite.cpp:2:0:
ResourceManager.cpp: In member function ‘type* sz::ResourceManager::Get(std::string) [with type = sz::Image, std::string = std::basic_string<char>]’:
Sprite.cpp:10:65:   instantiated from here
ResourceManager.cpp:50:15: error: cannot convert ‘sz::SoundBuffer*’ to ‘sz::Image*’ in return
ResourceManager.cpp: In member function ‘void sz::ResourceManager::AddNew(std::string) [with type = sz::Image, std::string = std::basic_string<char>]’:
ResourceManager.cpp:36:5:   instantiated from ‘type* sz::ResourceManager::Get(std::string) [with type = sz::Image, std::string = std::basic_string<char>]’
Sprite.cpp:10:65:   instantiated from here
ResourceManager.cpp:23:4: error: cannot convert ‘sz::Image*’ to ‘std::map<std::basic_string<char>, sz::SoundBuffer*>::mapped_type {aka sz::SoundBuffer*}’ in assignment
ResourceManager.cpp: In member function ‘type* sz::ResourceManager::Get(std::string) [with type = sz::Image, std::string = std::basic_string<char>]’:
ResourceManager.cpp:55:2: warning: control reaches end of non-void function [-Wreturn-type]
Compilation failed.

3 个答案:

答案 0 :(得分:0)

必须完全定义模板化函数,编译器才能使用它们。这意味着您必须将这些函数的主体从源文件移动到头文件。

修改

您必须检查模板类的使用方式。请参阅此错误消息:

  

ResourceManager.cpp:50:15:错误:无法将'sz :: SoundBuffer *'转换为'sz :: Image *'作为回报​​

除非sz::SoundBuffer继承自sz::Image,否则您的类型之间会不匹配。

答案 1 :(得分:0)

好的,看看代码和错误消息后,这是我的想法。

您无法从相同的功能返回图像和声音。它们是个人类型。您必须指定要返回的类型。当您将if / else放入模板时,它仍然会检查它是否可以返回所有这些类型,并且会失败。

你必须返回Image和Sound继承的BaseClass *(或任何你想要的名字)。

答案 2 :(得分:0)

“编译时间if”是通过模板部分特化完成的。但这里甚至不需要它:

template<typename type> struct Container {
  static std::map<std::string, type*> container;
};
std::map<std::string, sz::Image*>& ImagesContainer = Container<sz::Image>::container;
// etc...
template <class type>
void ResourceManager::AddNew(std::string filePath)
{
  type *item = new type(filePath);
  Container<type>::container[filePath] = item;
}