当T是float类型时,当我试图强制转换为T类的模板时,我似乎在下面的代码中得到了一个错误。我已经意识到int类型的功能是正确的,因为以下是有效的语法:
char* str = "3";
int num = (int)str;对于float就不是这样了。我想知道是否有一种方法可以阻止g++编译器在类型不匹配时出错,这样我就可以使用RTTI方法typeid()来处理它。
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++抛出的错误是:
source/Main.cpp:128: error: invalid cast from type ‘char*’ to type ‘float’发布于 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。您可以在编译时完全处理此问题:
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的情况下,你会得到一个编译时错误。我希望你能明白这一点。
发布于 2009-10-04 18:53:06
你需要在编译时进行分支。将模板中的内容更改为如下所示:
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中的代码与上面相同。如果有更多的情况需要特殊处理,我会使用这个:
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函数的重载更改为以下内容
// 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);
}然后,专门化将确定应该使用字符串和数字转换的“配置”。
发布于 2009-10-04 17:08:36
我不熟悉Lua,但我认为在这种情况下这无关紧要...
lua_toString的返回值显然是一个char*,这意味着您将获得值的地址,然后尝试将该地址转换为浮点数。看看strtod,看看如何更正确地完成这项工作,或者,正如sellibitze所指出的,使用stringstream。
https://stackoverflow.com/questions/1516845
复制相似问题