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