2015-12-31 3 views
0

Можно ли внедрить наш собственный код в QVariant :: canConvert?Замена QVariant :: Handler :: canConvert

Я добавить поддержку для преобразования нашего собственной ценности универсального контейнера и версии Qt (QVariant), основанные главным образом на предложение здесь How to support comparisons for QVariant objects containing a custom type?

Я довольно уверен, что ответ на этот вопрос " это не может быть сделано », просмотр источника показывает, что реализация QVariant :: canConvert не вызывает в обработчике, но я думал, что я все равно спрошу из-за болезненного любопытства.

https://github.com/qtproject/qt/blob/b05d05fd9ce2aeedfaf805a7ed9007a93c902bc9/src/corelib/kernel/qvariant.cpp#L2719

Есть ли случайное место в реализации QVariant, где мы можем получить какой-то крюк в этот вид функциональности (без перекомпиляции Qt), и если нет, то функция на Handler используется для чего/почему он существует? В основном - какие-либо предложения по работе вокруг этого?

ответ

2

Конечно, вы можете использовать QVariant::canConvert() с вашими пользовательскими типами данных. Единственное предостережение - вы должны зарегистрировать тип с помощью системы типов. Если вы этого не сделаете, вы получите дружеское напоминание через static_assert,

error: static assertion failed: Type is not registered, please use the Q_DECLARE_METATYPE macro to make it known to Qt's meta-object system

Например, этот код работает прекрасно,

struct Foo { 
    int a, b; 
}; 

Q_DECLARE_METATYPE(Foo) 


int main() 
{ 
     Foo foo {1, 2}; 
     QVariant variant = QVariant::fromValue(foo); 
     qDebug() << variant.canConvert<Foo>(); 
} 

, и если вы хотите изменить шаблон по умолчанию, все вам нужно это предоставить собственную специализацию, чтобы сделать, как вы хотите,

template<> 
bool QVariant::canConvert<Foo>() const { 
    qDebug() << "Hello from my specialization!"; 
    return userType() == qMetaTypeId<Foo>(); 
}; 

Там нет «обработчиков», потому что это все шаблонный. Просто будьте осторожны - хотя вы можете специализировать шаблоны, такие как QVariant :: value(), это не повлияет на QVariant :: toInt() и аналогично, даже если вы специализируетесь на случае int. Например,

template<> 
int QVariant::value<int>() const 
{ 
    if (userType() == qMetaTypeId<Foo>()) { 
     return value<Foo>().a + value<Foo>().b; 
    }; 

    return toInt(); 
} 

.... 

qDebug() << variant.value<int>() << variant.toInt(); 

производит

3 0

+0

Спасибо, это ответ на мой вопрос очень хорошо! – FrozenKiwi

+0

Это «работает», но я предполагаю, что однажды можно специализировать, например, значение «()», иначе вы получите конфликты имен во время компиляции, поэтому нужно добавить все настраиваемые типы в одну специализацию? Кроме того, я предлагаю добавить 'canConvert' для ясности' template <> bool QVariant :: canConvert () const {if (userType() == QMetaTypeId ()) {return true; } else {return canConvert (qMetaTypeId ()); }} 'или иначе он прерывает все остальные вызовы' canConvert() ' –

Смежные вопросы