无法在初始化时将std :: string转换为

时间:2014-08-16 00:28:52

标签: c++

我遇到了一个奇怪的问题:

metadata.h:

class metadata
{
    public:
        metadata ( std::string filename );
        template <class T> T get ( std::string key ) { return m_data.get<T> ( key ); }
    private:
        boost::property_tree::ptree m_data;
};

metadata.cpp:

metadata::metadata ( std::string filename )
{
    try {
        boost::property_tree::read_info ( filename, m_data );
    } catch ( boost::property_tree::file_parser_error err ) {
        std::cerr << "[!] Unable to open "
                  << filename
                  << ": "
                  << err.message()
                  << "!"
                  << std::endl;
        throw except ( "Error opening metadata file." );
    }
}

asset.h:

template <class T> class assetManager {
    public:
        void load ( std::string filename );
        T get ( std::string filename );
        T operator[] ( std::string filename );
        void drop ( std::string filename ) { m_assets.erase ( filename ); }
        void clear() { m_assets.clear(); }
    private:
        std::map<std::string,T> m_assets;
};

template <class T> void assetManager<T>::load ( std::string filename )
{
    if ( m_assets [ filename ] == nullptr ) {
        m_assets.erase ( filename );
        m_assets.insert ( std::pair <std::string,T> ( filename, new T ( filename ) ) );
    }
}

template <class T> T assetManager<T>::get ( std::string filename )
{
    T ret = m_assets.at ( filename );
    return ret;
}

出于某种原因,这一行在这里:

m_metadata.load ( boost::filesystem::current_path().string() + "/engine.conf" );

我从g ++获得以下编译器错误:

src / core /../ core /../ asset / asset.h | 22 |错误:初始化时无法将'std :: string {aka std :: basic_string}'转换为'metadata *'

在任何情况下,据我所知,我编程的东西甚至有点类似于将字符串转换为我的元数据指针。有什么想法吗?

2 个答案:

答案 0 :(得分:1)

assetManager<T>::load内部这个子表达式

std::pair <std::string,T> ( filename, new T ( filename ) )

显然是不正确的。 new T将生成T *。与此同时,您的对被宣布为T作为其第二个成员。除非T *中有正确的转化构造函数,否则您无法使用T初始化T

如果Tmetadata,那么针对此问题,我实际上会发出一条错误消息,指出无法将metadata *转换为std::string,而不是另一种方式。如果您尝试这个

,您将看到相同的错误
metadata m(new metadata("test"));

另一个问题是您正在创建第一个成员具有类型std::string的对。但是,在std::map<std::string, T>::value_type中,该对中的第一个成员实际上是const std::string。代码将进行编译,但需要从std::pair<std::string, T>转换为地图std::pair<const std::string, T>。这可能会成为性能问题。这就是为什么更好的想法是使用std::map<std::string, T>::value_type作为对类型,而不是试图手动拼写出来。


在评论中,您声明m_metadataassetManager<metadata*>。在这种情况下,Tmetadata *。这解释了一切,包括错误消息。在这种情况下,问题更加简单和本地化。此

new T ( filename )

单独是导致错误的原因。这意味着new T会生成metadata *个对象,并尝试使用std::string初始化它。因此错误消息。无法使用metadata *初始化std::string,因为无法将std::string转换为metadata *

最重要的是,这样的new表达式将返回metadata **值,这绝对不是您需要的值。

答案 1 :(得分:0)

我将m_metadata更改为assetManager,然后进行了一些更改:

template <class T> class assetManager {
    public:
        void load ( std::string filename );
        T get ( std::string filename );
        T operator[] ( std::string filename );
        void drop ( std::string filename ) { m_assets.erase ( filename ); }
        void clear() { m_assets.clear(); }
    private:
        std::map<std::string,T*> m_assets;
};

template <class T> void assetManager<T>::load ( std::string filename )
{
    if ( m_assets [ filename ] == nullptr ) {
        m_assets.erase ( filename );
        m_assets.insert ( std::pair <std::string,T*> ( filename, new T ( filename ) ) );
    }
}

template <class T> T assetManager<T>::get ( std::string filename )
{
    T ret = *m_assets.at ( filename );
    return ret;
}

它现在编译并运行。虽然我的问题已得到解决但 对我来说仍然是一个谜,为什么编译器认为我正在尝试将std :: string转换为元数据*。