Introduce Q_STATIC_ASSERT
authorJędrzej Nowacki <jedrzej.nowacki@nokia.com>
Fri, 14 Oct 2011 10:58:54 +0000 (12:58 +0200)
committerQt by Nokia <qt-info@nokia.com>
Wed, 19 Oct 2011 17:25:37 +0000 (19:25 +0200)
Example of message of failed assert (gcc 4.6, file tst_qglobal.cpp:300):
tst_qglobal.cpp:300:92: error: invalid application of ‘sizeof’
to incomplete type ‘QStaticAssertFailure<false>’

Change-Id: Ic1798094f718eaad388d754034115aafbbb6bd5e
Reviewed-by: João Abecasis <joao.abecasis@nokia.com>
src/corelib/global/qglobal.h
tests/auto/corelib/global/qglobal/tst_qglobal.cpp

index 5f8e6be..ee60185 100644 (file)
@@ -1785,6 +1785,15 @@ Q_CORE_EXPORT void qt_assert_x(const char *where, const char *what, const char *
 #  endif
 #endif
 
+// Intentionally undefined
+template <bool Test> class QStaticAssertFailure;
+template <> class QStaticAssertFailure<true> {};
+
+#define Q_STATIC_ASSERT_PRIVATE_JOIN(A, B) Q_STATIC_ASSERT_PRIVATE_JOIN_IMPL(A, B)
+#define Q_STATIC_ASSERT_PRIVATE_JOIN_IMPL(A, B) A ## B
+#define Q_STATIC_ASSERT(...) \
+    enum {Q_STATIC_ASSERT_PRIVATE_JOIN(q_static_assert_result, __LINE__) = sizeof(QStaticAssertFailure<bool(__VA_ARGS__)>)}
+
 Q_CORE_EXPORT void qt_check_pointer(const char *, int);
 Q_CORE_EXPORT void qBadAlloc();
 
index 85aa03f..9dc78a1 100644 (file)
@@ -52,6 +52,7 @@ private slots:
     void qassert();
     void qtry();
     void checkptr();
+    void qstaticassert();
 };
 
 void tst_QGlobal::qIsNull()
@@ -267,5 +268,72 @@ void tst_QGlobal::checkptr()
     QCOMPARE(q_check_ptr(c), c);
 }
 
+// Check Q_STATIC_ASSERT, It should compile
+// note that, we are not able to test Q_STATIC_ASSERT(false), to do it manually someone has
+// to replace expressions (in the asserts) one by one to false, and check if it breaks build.
+class MyTrue
+{
+public:
+    MyTrue()
+    {
+        Q_STATIC_ASSERT(true);
+        Q_STATIC_ASSERT(!false);
+    }
+    ~MyTrue()
+    {
+        Q_STATIC_ASSERT(true);
+        Q_STATIC_ASSERT(!false);
+    }
+    Q_STATIC_ASSERT(true);
+    Q_STATIC_ASSERT(!false);
+};
+
+struct MyExpresion
+{
+    void foo()
+    {
+        Q_STATIC_ASSERT(sizeof(MyTrue) > 0);
+        Q_STATIC_ASSERT(sizeof(MyTrue) > 0);
+    }
+private:
+    Q_STATIC_ASSERT(sizeof(MyTrue) > 0);
+    Q_STATIC_ASSERT(sizeof(MyTrue) > 0);
+};
+
+struct TypeDef
+{
+    typedef int T;
+    Q_STATIC_ASSERT(sizeof(T));
+};
+
+template<typename T1, typename T2>
+struct Template
+{
+    static const bool True = true;
+    typedef typename T1::T DependentType;
+    Q_STATIC_ASSERT(True);
+    Q_STATIC_ASSERT(!!True);
+    Q_STATIC_ASSERT(sizeof(DependentType));
+    Q_STATIC_ASSERT(!!sizeof(DependentType));
+};
+
+struct MyTemplate
+{
+    Q_STATIC_ASSERT(Template<TypeDef, int>::True);
+    Q_STATIC_ASSERT(!!Template<TypeDef, int>::True);
+};
+
+void tst_QGlobal::qstaticassert()
+{
+    // Force compilation of these classes
+    MyTrue tmp1;
+    MyExpresion tmp2;
+    MyTemplate tmp3;
+    Q_UNUSED(tmp1);
+    Q_UNUSED(tmp2);
+    Q_UNUSED(tmp3);
+    QVERIFY(true); // if the test compiles it has passed.
+}
+
 QTEST_MAIN(tst_QGlobal)
 #include "tst_qglobal.moc"