[Development] User-defined literals for QString (and QByteArray)

Thiago Macieira thiago.macieira at intel.com
Fri Mar 5 20:04:57 CET 2021


On Friday, 5 March 2021 04:40:24 PST Lars Knoll wrote:
> I wish we had a good way of adding that overloaded constructor to QString.
> Unfortunately, we have lots of API that is overloaded on both QString and
> QStringView. Adding the constructor to QString will then cause ambiguities
> wherever we have overloaded API taking both a QString and a QStringView.
> 
> I wish there was a way to tell the compiler to prefer one conversion over
> the other ("if you have the choice, always use QStringView and not
> QString”), but C++ doesn’t have a way to do that.

There an ugly way. By making one of the two a template function, it lowers in 
priority for matching.

template <typename T> 
std::enable_if_t<std::is_same_v<T, QString>> f(const T &);
void f(QStringView);

void g()
{
    f(u"Hello");
}
<https://gcc.godbolt.org/z/bMhGrx>

The problem is that changing existing QString methods to be templates is 
binary incompatible. That means we can't add QStringView overloads where 
QString parameters already exist and are out-of-line (remember: any non-
template method in an exported class is out of line for the purposes of BC).

Another one is to add the constructor to QString, but make it explicit. So you 
can still work on char16_t literals, but you may need to wrap it on QString():

void g1()
{
    f(QString(u"Hello"));
}
<https://gcc.godbolt.org/z/oeceEW>

The problem in this one is that it's far easier to write f("Hello") than the 
slightly more efficient f(QString(u"Hello")). For this, an UDL would help.

And it's really only *slightly* more efficient. Previous benchmarks have shown 
that going through the UTF-8 decoder adds 2-5% loss compared to memcpy() and 
that time is dwarfed anyway by the cost of allocating memory.

-- 
Thiago Macieira - thiago.macieira (AT) intel.com
  Software Architect - Intel DPG Cloud Engineering





More information about the Development mailing list