如何将字符串解析为C++类型名称?

3
如何实现 atot(),使其根据类型使用 atof()atoi()atol()? 目前它对所有类型都使用 atof()
template<typename T>
T Mtx<T>::atot(const char *s) const
{
    return atof(s);
}

请注意速度非常重要。


4
如何专攻? - imreal
为什么这是一个成员函数?您希望它根据类型 T 选择函数吗? - Joseph Mansfield
@Nick,我不知道这是什么。如果这是一个解决方案,请将其发布为答案。谢谢。 - Serg
@sftrabbit,没有特别的原因。我可以将它设为静态的。 - Serg
5个回答

3

boost::lexical_cast<T> 可以基本实现这个功能。

template<typename T>
T Mtx<T>::atot(const char *s) const
{
    return boost::lexical_cast<T>(s);
}

示例:

#include <boost/lexical_cast.hpp>

template<typename T>
T atot(const char *s)
{
    return boost::lexical_cast<T>(s);
}

int main()
{
    auto i = atot<int>("3");
    auto d = atot<double>("-INF");
    auto f = atot<double>("314e-2");
    auto ul = atot<unsigned long>("65537");
}

lexical_cast 可能不如 C 函数调用快? - billz
@billz 可能会,也可能不会。如果我没记错的话,boost lexical_cast 是为内置数值类型专门设计的,如果它没有这样的专门化,它会退回到使用流提取。不过你可能需要对此进行性能分析。 - sehe

3
最直接的解决方案是专业化:
template<>
double Mtx<double>::atot(const char *s) const
{
    return atof(s);
}

template<>
int Mtx<int>::atot(const char *s) const
{
    return atoi(s);
}

3

专业化是根据特定的类型创建模板的特殊实现。

在这种情况下,您可以这样做:

template<>
float Mtx<float>::atot(const char *s) const
{
    return atof(s);
}

template<>
int Mtx<int>::atot(const char *s) const
{
    return atoi(s);
}

如果你使用atot函数时,传入的参数类型是float或者int,那么将会使用上述的实现方式。对于其他类型的参数,则会使用你已经有的通用实现。


这段代码无法编译。但是如果分别用float和int代替T,它们就能编译。这里是否有打字错误? - Serg
@Serg,是的,那是个打字错误 :) 已经修复了。 - imreal

2

我真的不明白你为什么想要这个。调用正确的方法似乎同样简单。

但是像下面这种情况呢?

void atot(const char *s, float& result)
{
    result = atof(s);
}

void atot(const char *s, long& result)
{
    result = atol(s);
}

void atot(const char *s, int& result)
{
    result = atoi(s);
}

1

如果类型出现在参数中的一个中,您可以重载函数。因此,您需要使用输出参数而不是返回值:

void atonum(const char*, int&);
void atonum(const char*, long&);
void atonum(const char*, float&);

如果您不喜欢这个,可以使用模板特化。请参阅其他关于此的答案。

或者您可以将重载与包装器模板结合使用:

template<typename T> void atonum(const char* a)
{
    T tmp;
    atonum(a, tmp);
    return tmp;
}

但是这仍然像专用模板一样难看。

您可以通过重载类型转换运算符来获得更好的语法,以便于调用者。 概念证明:

#include <cstdio>
#include <cstdlib>
struct atonum
{
    atonum(const char* a):m_a(a){}
    operator int(){printf("int\n"); return atoi(m_a);}
    operator long(){printf("long\n"); return atol(m_a);}
    operator float(){printf("float\n"); return atof(m_a);}
private:
    const char* m_a;
};
int main(int argc, const char* argv[])
{
    int i = atonum("1");
    long l = atonum("2");
    float f = atonum("3.0");
    return i+l+f;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接