0

そのため、C++で作業しているゲームのResourceManagerクラスに少し問題があります。だから私は通常の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.
4

3 に答える 3

0

The templated function have to be completely defined for the compiler to able to use them. That means you have to move the body of those function from the source file to the header file.

Edit:

You have to check the how you use the template class. See for example this error message:

ResourceManager.cpp:50:15: error: cannot convert ‘sz::SoundBuffer*’ to ‘sz::Image*’ in return

Unless sz::SoundBuffer inherits from sz::Image you have a mismatch between types.

于 2012-04-16T11:56:59.613 に答える
0

わかりました、これはコードとエラーメッセージを見た後の私の考えです。

そのような同じ関数から画像と音声を返すことはできません。それらは個別のタイプです。また、返されるタイプを指定する必要があります。テンプレートにif/elseを入れると、それらすべての型を返すことができるかどうかがチェックされ、失敗します。

ImageとSoundの両方が継承するBaseClass*(またはそれを呼び出したいもの)を返す必要があります。

于 2012-04-16T12:06:32.043 に答える
0

「コンパイル時の場合」は、テンプレートの部分的な特殊化を介して行われます。しかし、ここではそれも必要ありません:

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;
}
于 2012-04-16T14:56:53.220 に答える