Как реализовать atot()
так что он использует atof()
, atoi()
, или же atol()
по типу?
В настоящее время он использует atof()
для всех типов:
template<typename T>
T Mtx<T>::atot(const char *s) const
{
return atof(s);
}
Обратите внимание, что скорость очень важна.
Самым простым решением является специализация:
template<>
double Mtx<double>::atot(const char *s) const
{
return atof(s);
}
template<>
int Mtx<int>::atot(const char *s) const
{
return atoi(s);
}
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");
}
Специализация — это создание специальных реализаций шаблона в зависимости от конкретного типа.
В этом случае вы можете сделать это:
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
, тогда будут использованы вышеуказанные реализации. Для любого другого типа будет использоваться тот, который у вас уже есть.
Я действительно не понимаю, почему вы этого хотите. Кажется, так же легко вызвать правильный метод.
Но как насчет чего-то вроде следующего?
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);
}
Вы можете перегрузить функцию, если тип указан в одном из параметров. Таким образом, вам потребуется параметр out вместо возвращаемого значения:
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;
}