По вашему вопросу я не могу сказать, знаете ли вы это или нет, но вы действительно можете сделать это с помощью шаблона. Единственный улов в том, что вам придется указывать тип, из которого вы конвертируете в каждом вызове, вместо того, чтобы полагаться на логический вывод (поскольку, как вы сказали, тип аргумента всегда будет одинаковым).
template<typename T> T parse(const string& str) { /* do stuff for other types */ }
template<> int parse<int>(const string& str) { /* do stuff for ints */ }
template<> double parse<double>(const string& str) { /* do stuff for doubles */ }
template<> bool parse<bool>(const string& str) { /* do stuff for bools */ }
// etc.
А затем вызвать как
int value = parse<int>("37");
double value = parse<double>("3.14");
bool value = parse<bool>("true");
Если вы уже знали это, просто проигнорируйте этот ответ, но из вашего вопроса не ясно, что вы знаете, что это возможно.
Конечно, если то, что вы делаете, не является действительно общим (и поэтому вы должны специализироваться для каждого типа, который хотите анализировать), то написание шаблона в любом случае не является правильным решением.
Кстати, вы можете сделать это довольно обобщенно с помощью одной функции, подобной этой (при условии, что синтаксический анализ - это то, что вы действительно хотите сделать):
#include <sstream>
template<typename T> T parse(const string& str)
{
T t;
std::istringstream sstr(str);
sstr >> t;
return t;
}
Это будет работать для любого строимого по умолчанию, извлекаемого потоком типа, который включает все встроенные модули.