首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >模板投射问题

模板投射问题
EN

Stack Overflow用户
提问于 2009-10-04 16:44:47
回答 6查看 643关注 0票数 0

当T是float类型时,当我试图强制转换为T类的模板时,我似乎在下面的代码中得到了一个错误。我已经意识到int类型的功能是正确的,因为以下是有效的语法:

代码语言:javascript
复制
char* str = "3";
int num = (int)str;

对于float就不是这样了。我想知道是否有一种方法可以阻止g++编译器在类型不匹配时出错,这样我就可以使用RTTI方法typeid()来处理它。

代码语言:javascript
复制
class LuaConfig {
    // Rest of code omitted...

    // template currently supports both string and int
    template <class T> T getC(const char *key) {
        lua_pushstring(luaState, key);
        lua_gettable(luaState, -2);
        if (!lua_isnumber(luaState, -1)) {
            // throw error
            std::cout << "NOT A NUMBER" << std::endl;
        }

        T res;
        // WHERE THE PROBLEM IS:
        if (    typeid(T) == typeid(int)
             || typeid(T) == typeid(float)
        ) {
            std::cout << "AS NUM" << std::endl;
            // Floats should fall in here, but never does because of the
            // else clause failing at compile time.
            res = (T)lua_tonumber(luaState, -1);
        } else {
            // TODO: Fails on float here, it should fall down the
            // first branch (above). This branch should only be for string data.
            std::cout << "AS STRING" << std::endl;
            res = (T)lua_tostring(luaState, -1);        // LINE THAT CAUSES ISSUE.
        }

        std::cout << "OUT:" << res << std::endl;

        lua_pop(luaState, 1);
        return res;
    }
}

int main( int argc, char* args[] ) {
    LuaConfig *conf = new LuaConfig();
    std::cout << conf->getC<int>("width") << std::endl;
    std::cout << conf->getC<float>("width") << std::endl;       // This causes the error.
}

g++抛出的错误是:

代码语言:javascript
复制
source/Main.cpp:128: error: invalid cast from type ‘char*’ to type ‘float’
EN

回答 6

Stack Overflow用户

发布于 2009-10-04 16:50:13

尽量避免C风格的强制转换。如果你写(int)ptr,其中ptr是一些指针,这将是一个reinterpret_cast,这可能不是你想要的。要将数字转换为字符串,然后再转换回来,请检查各种常见问题。要做到这一点,一种方法是使用std::stringstream类。

C风格的造型是危险的,因为它可以用于很多事情,而且它的作用并不总是很明显。C++提供了其他选择(static_cast、dynamic_cast、const_cast、reinterpret_cast)和相当于静态强制转换的函数式强制转换。

对于( int )ptr,它将指针转换为int类型,而不是指针所指向的数字的字符串表示形式。

您可能还想查看一下Boost's lexical_cast

编辑:不要使用typeid。您可以在编译时完全处理此问题:

代码语言:javascript
复制
template<typename T> struct doit; // no definition
template<> struct doit<int> {
    static void foo() {
        // action 1 for ints
    }
};
template<> struct doit<float> {
    static void foo() {
        // action 2 for floats
    }
};

....

template<typename T> void blah(T x) {
    // common stuff
    doit<T>::foo(); // specific stuff
    // common stuff
}

在T既不是int也不是float的情况下,你会得到一个编译时错误。我希望你能明白这一点。

票数 2
EN

Stack Overflow用户

发布于 2009-10-04 18:53:06

你需要在编译时进行分支。将模板中的内容更改为如下所示:

代码语言:javascript
复制
   template<typename T> struct id { };

   // template currently supports both string and int
    template <class T> T getC(const char *key) {
        lua_pushstring(luaState, key);
        lua_gettable(luaState, -2);
        if (!lua_isnumber(luaState, -1)) {
            // throw error
            std::cout << "NOT A NUMBER" << std::endl;
        }

        T res = getCConvert(luaState, -1, id<T>())
        std::cout << "OUT:" << res << std::endl;

        lua_pop(luaState, 1);
        return res;
    }

    // make the general version convert to string
    template<typename T>
    T getCConvert(LuaState s, int i, id<T>) { 
      return (T)lua_tostring(s, i); 
    }

    // special versions for numbers
    float getCConvert(LuaState s, int i, id<int>) { 
      return (float)lua_tonumber(s, i); 
    }

    int getCConvert(LuaState s, int i, id<float>) { 
      return (int)lua_tonumber(s, i); 
    }

有几个alternative ways可以解决这个问题。为了避免重复添加重载,boost::enable_if可能很有用。但只要你只有int和float两种特殊情况,我会保持简单,只需重复一次对lua_tonumber的调用。

另一种避免enable_if并仍然避免重复重载的模式是引入类型为flags的层次结构-将id更改为以下内容,并保持getC中的代码与上面相同。如果有更多的情况需要特殊处理,我会使用这个:

代码语言:javascript
复制
template<typename T> struct tostring { };
template<typename T> struct tonumber { };

template<typename T> struct id : tostring<T> { };
template<> struct id<int> : tonumber<int> { };
template<> struct id<float> : tonumber<float> { };

id现在需要在类模板之外定义,因为您不能在模板中显式地专门化它。然后将helper函数的重载更改为以下内容

代码语言:javascript
复制
    // make the general version convert to string
    template<typename T>
    T getCConvert(LuaState s, int i, tostring<T>) { 
      return (T)lua_tostring(s, i); 
    }

    // special versions for numbers
    template<typename T>
    T getCConvert(LuaState s, int i, tonumber<T>) { 
      return (T)lua_tonumber(s, i); 
    }

然后,专门化将确定应该使用字符串和数字转换的“配置”。

票数 1
EN

Stack Overflow用户

发布于 2009-10-04 17:08:36

我不熟悉Lua,但我认为在这种情况下这无关紧要...

lua_toString的返回值显然是一个char*,这意味着您将获得值的地址,然后尝试将该地址转换为浮点数。看看strtod,看看如何更正确地完成这项工作,或者,正如sellibitze所指出的,使用stringstream。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1516845

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档