Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert QString to typename using templates?

Tags:

c++

templates

qt

I would like to write a generic template method that computes some things and in the end returns a value of typename T. The value comes from a QString so I need to convert the QString to the specified typename T. Unfortunately I only find the toDouble(), toInt(),... methods.

What I need is:

QString s = 3.1415;
double d = s.toType<double>();
float f = s.toType<float>();
int i = s.toType<int>();

I don't want to call the toDouble(), toInt(),... because I cannot select them at compile time.

Thanks!


Edit: I could write my own specialized template functions that do exactly this. So

double myOwnConvertFunction<double>(const QString& s)

would then simply call the s.toDouble()

I thought that Qt might already have a built-in way?

like image 406
FrozenTarzan Avatar asked Nov 03 '15 14:11

FrozenTarzan


3 Answers

You can convert the QString to QVariant and then use value<T>()

QVariant(s).value<T>()

QVariant shares the data with QString, so no deep copy happens here and the result should be pretty fast as well. For extra comfort, Qt has

qvariant_cast<T>(s)
like image 176
Johannes Schaub - litb Avatar answered Nov 15 '22 06:11

Johannes Schaub - litb


You'll want to use a QTextStream. You can do it using the QTextStream's QString constructor. Your code will probably look something like this:

template <typename T>
T toType(const QString& string) {
    T result;
    QTextStream stream(&string, QIODevice::ReadOnly);

    stream >> result;
    return result;
}

Incidentally, depending on whether you are suffering from the pre-gcc 5.0 stringstream move-constructor bug you can also accomplish the QTextStream construction inline like so:

template <typename T>
T toType(const QString& string) {
    T result;

    QTextStream(&string, QIODevice::ReadOnly) >> result;
    return result;
}   
like image 38
Jonathan Mee Avatar answered Nov 15 '22 06:11

Jonathan Mee


You could write a non-member toType:

template <typename T> struct type { };

template <typename T>
auto toType(QString const& q)
    -> decltype(toType(q, type<T>{}))
{
    return toType(q, type<T>{});
}

with a bunch of overloads as appropriate:

double toType(QString const& q, type<double> ) {
    return q.toDouble();
}

int toType(QString const& q, type<int> ) {
    return q.toInt();
}

float toType(QString const& q, type<float> ) {
    return q.toFloat();
}

...
like image 1
Barry Avatar answered Nov 15 '22 07:11

Barry