diff --git a/autotests/libs/itemhydratest.h b/autotests/libs/itemhydratest.h --- a/autotests/libs/itemhydratest.h +++ b/autotests/libs/itemhydratest.h @@ -37,7 +37,8 @@ void testItemCopy(); void testEmptyPayload(); void testPointerPayload(); - void testPolymorphicPayload(); + void testPolymorphicPayloadWithTrait(); + void testPolymorphicPayloadWithTypedef(); void testNullPointerPayload(); void testQSharedPointerPayload(); void testHasPayload(); diff --git a/autotests/libs/itemhydratest.cpp b/autotests/libs/itemhydratest.cpp --- a/autotests/libs/itemhydratest.cpp +++ b/autotests/libs/itemhydratest.cpp @@ -64,6 +64,8 @@ { return new Gerd(*this); } + + typedef Volker SuperClass; }; typedef std::shared_ptr GerdPtr; @@ -79,7 +81,6 @@ namespace Akonadi { template <> struct SuperClass : public SuperClassTrait {}; -template <> struct SuperClass : public SuperClassTrait {}; } QTEST_MAIN(ItemHydra) @@ -215,7 +216,7 @@ QCOMPARE(w.use_count(), (long)0); } -void ItemHydra::testPolymorphicPayload() +void ItemHydra::testPolymorphicPayloadWithTrait() { VolkerPtr p(new Rudi); @@ -252,6 +253,43 @@ } } +void ItemHydra::testPolymorphicPayloadWithTypedef() +{ + VolkerPtr p(new Gerd); + + { + Item i1; + i1.setPayload(p); + QVERIFY(i1.hasPayload()); + QVERIFY(i1.hasPayload()); + QVERIFY(!i1.hasPayload()); + QVERIFY(i1.hasPayload()); + QCOMPARE(p.use_count(), (long)2); + { + auto p2 = std::dynamic_pointer_cast(i1.payload< VolkerPtr >()); + QCOMPARE(p.use_count(), (long)3); + QCOMPARE(p2->who, QStringLiteral("Gerd")); + } + + { + auto p2 = i1.payload< GerdPtr >(); + QCOMPARE(p.use_count(), (long)3); + QCOMPARE(p2->who, QStringLiteral("Gerd")); + } + + bool caughtException = false; + try { + auto p3 = i1.payload(); + } catch (const Akonadi::PayloadException &e) { + qDebug() << e.what(); + caughtException = true; + } + QVERIFY(caughtException); + + QCOMPARE(p.use_count(), (long)2); + } +} + void ItemHydra::testNullPointerPayload() { RudiPtr p((Rudi *)nullptr); diff --git a/src/core/supertrait.h b/src/core/supertrait.h --- a/src/core/supertrait.h +++ b/src/core/supertrait.h @@ -23,15 +23,24 @@ namespace Akonadi { +namespace Internal { +template struct check_type{ typedef void type; }; +} + /** @internal - @see super_class + @see SuperClass */ -template +template struct SuperClassTrait { typedef Super Type; }; +template +struct SuperClassTrait::type> { + typedef typename Class::SuperClass Type; +}; + /** Type trait to provide information about a base class for a given class. Used eg. for the Akonadi payload mechanism. @@ -43,6 +52,10 @@ template <> struct SuperClass : public SuperClassTrait{}; } @endcode + + Alternatively, define a typedef "SuperClass" in your type, pointing to the base class. + This avoids having to include this header file if that's inconvenient from a dependency + point of view. */ template struct SuperClass : public SuperClassTrait {}; }