Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-39545

QList only works if T has a copy-operator

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Won't Do
    • Icon: P4: Low P4: Low
    • None
    • 5.2.0, 5.2.1, 5.3.0
    • None
    • MinGW 4.8.2

      "qlist.h line 370 (Qt 5.3.0 sources)"
      template <typename T>
      Q_INLINE_TEMPLATE void QList<T>::node_construct(Node *n, const T &t)
      {
          if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) n->v = new T(t);
          else if (QTypeInfo<T>::isComplex) new (n) T(t);
      #if (defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__IBMCPP__)) && !defined(__OPTIMIZE__)
          // This violates pointer aliasing rules, but it is known to be safe (and silent)
          // in unoptimized GCC builds (-fno-strict-aliasing). The other compilers which
          // set the same define are assumed to be safe.
          else *reinterpret_cast<T*>(n) = t;
      #else
          // This is always safe, but penaltizes unoptimized builds a lot.
          else ::memcpy(n, static_cast<const void *>(&t), sizeof(T));
      #endif
      }
      

      As everything is in one method. Every part has to compile for every type.

      If I have a T class which is not copyable:

      "Column.h"
      class Column
      {
          Column& operator =(const Column& src) = delete;
      
      public:
          explicit Column(const QString &name);
      
      private:
          const QString m_name;
      }
      

      The QList<Column> is only valid with GCC in release mode.

      suggested solution:

      • use template specialisation to split the code at compile time.
      "Add to QList<T>"
          template < int isSeparate, int isComplex, int dummy = 1 >
          struct NodeConstructor;
      
      "Extend node_construct"
      template <typename T>
      template <int isComplex>
      struct QList<T>::NodeConstructor<true, isComplex> {
          static void construct(QList<T>::Node *n, const T &t) {
              n->v = new T(t);
          }
      };
      
      template <typename T>
      template <int dummy>
      struct QList<T>::NodeConstructor<false, true, dummy> {
          static void construct(QList<T>::Node *n, const T &t) {
              new (n) T(t);
          }
      };
      
      template<typename T>
      template<int dummy>
      struct QList<T>::NodeConstructor<false, false, dummy> {
          static void construct(QList<T>::Node *n, const T &t) {
      #if (defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__IBMCPP__)) && !defined(__OPTIMIZE__)
              // This violates pointer aliasing rules, but it is known to be safe (and silent)
              // in unoptimized GCC builds (-fno-strict-aliasing). The other compilers which
              // set the same define are assumed to be safe.
              *reinterpret_cast<T*>(n) = t;
      #else
              // This is always safe, but penaltizes unoptimized builds a lot.
              ::memcpy(n, static_cast<const void *>(&t), sizeof(T));
      #endif
          }
      };
      
      template <typename T>
      Q_INLINE_TEMPLATE void QList<T>::node_construct(Node *n, const T &t)
      {
          NodeConstructor<QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic, QTypeInfo<T>::isComplex>::construct(n, t);
      }
      

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

            Unassigned Unassigned
            arbmind Andreas Reischuck
            Votes:
            4 Vote for this issue
            Watchers:
            5 Start watching this issue

              Created:
              Updated:
              Resolved:

                There are no open Gerrit changes