Pergunta

How to implement atot() so it uses atof(), atoi(), or atol() according to the type? Currently it uses atof() for all types:

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

Please note that speed is very important.

Foi útil?

Solução

The most straight-forward solution is to specialize:

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

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

Outras dicas

boost::lexical_cast<T> should do this, basically

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

Demo:

#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");
}

Specializing is creating special implementations of the template depending on a particular type.

In this case you could do this:

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

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

... and so on

So if you use atot with float or with int, then the above implementations will be used. For any other type, the generic one you already have will be used.

I really don't get why you want this. It seems just as easy to call the right method.

But what about something like the following?

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);
}

You can overload a function, if the type appears in one of the parameters. So you'll need an out parameter instead of the return value:

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

If you don't like this, you can use template specialization. See other answers about this.

Or you can combine the overload with a wrapper template:

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

But that's still as ugly to call as the specialized templates.

You can get a nicer syntax, for the caller, by overloading type conversion operators. Proof of concept:

#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;
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top