Чтобы разделить регистр для параметра t
типа t
с помощью SFINAE, я хочу знать, если оператор
QVariant::fromValue(t);
и/или
QVariant::value<T>();
компилирует. Если один компилируется, другой делает тоже, если вы не взломаете систему мета-типа. Они компилируются, если и только если t
было объявлено с помощью Q_DECLARE_METATYPE(T)
.
Очень простой пример использования, когда вы хотите напечатать тип значения, просто qDebugging эквивалентный вариант, если и только если поддерживается системой мета-типа (мне это не нужно, но это показывает проблему в минимальном примере):
template<class T> // enable if T NOT registered in the Qt meta type system
void print(const T &t) {
qDebug() << t;
}
template<class T> // enable if T registered in the Qt meta type system
void print(const T &t) {
qDebug() << QVariant::fromValue<T>();
}
Я знаю несколько (но похожих) возможностей для этого, но все они вводят некоторые вспомогательные структуры, сложные enable_if и т.д. Теперь я знаю, что есть QTypeInfo
, который, я думаю, уже предоставляет нечто вроде "объявлен" в системе типа Qt типа "тип". Однако этот класс не документирован, и поэтому он не предлагается использовать в долгосрочном и продуктивном коде, поскольку он может меняться между версиями Qt.
Есть ли простой способ (проще, чем с помощью "checker" + enable_if) проверять специализацию SFINAE, если тип t
поддерживается QVariant?
Обратите внимание, что решение по-прежнему должно быть переносимым между различными версиями Qt (Qt4 и Qt5 могут использовать другое определение QTypeInfo
). Однако я использую С++ 11, поэтому у меня есть доступ к std::enable_if
, например.
"Не переносимым" способом является использование внутреннего определения QMetaTypeId2<T>::Defined
в enable_if
(это значение перечисления, определяемое как 0 или 1). Таким образом, рабочим решением будет:
template<class T>
typename std::enable_if<!QMetaTypeId2<T>::Defined>::type
print(const T &t) {
qDebug() << t;
}
template<class T>
typename std::enable_if<QMetaTypeId2<T>::Defined>::type
print(const T &t) {
qDebug() << QVariant::fromValue<T>();
}
Однако, поскольку QMetaTypeId2
не документирован и только внутренний материал, он не должен появляться в клиентском коде.