Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Special Interest Groups
  3. C++ Gurus
  4. Template: Force const parameter
QtWS25 Last Chance

Template: Force const parameter

Scheduled Pinned Locked Moved Solved C++ Gurus
c++template
13 Posts 4 Posters 5.0k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • Joel BodenmannJ Offline
    Joel BodenmannJ Offline
    Joel Bodenmann
    wrote on last edited by Joel Bodenmann
    #3

    The problem with that is that then the user/caller of that method has to write code like this:

    QList<const MyLibraryItem*> myLibraryItems = mimeData->libraryItems<MyLibraryItem*>();
    

    In my opinion that is just a no-go. You'd expect the two template parameters to be the same in that assignment.

    Industrial process automation software: https://simulton.com
    Embedded Graphics & GUI library: https://ugfx.io

    kshegunovK 1 Reply Last reply
    0
    • Joel BodenmannJ Joel Bodenmann

      The problem with that is that then the user/caller of that method has to write code like this:

      QList<const MyLibraryItem*> myLibraryItems = mimeData->libraryItems<MyLibraryItem*>();
      

      In my opinion that is just a no-go. You'd expect the two template parameters to be the same in that assignment.

      kshegunovK Offline
      kshegunovK Offline
      kshegunov
      Moderators
      wrote on last edited by
      #4

      @Joel-Bodenmann
      Actually:

      QList<const MyLibraryItem *> myLibraryItems = mimeData->libraryItems<MyLibraryItem>();
      

      But yes, they differ. Whether or not it's acceptable it's up to you, I know of no other way.

      PS.
      I think a fat notice in the docs should be just enough. This isn't c++11 so what's on the left can be different from what's on the right (i.e. there's no auto confusing code). It's still valid to write:

      QWidget * button = new QToolButton();
      

      Read and abide by the Qt Code of Conduct

      1 Reply Last reply
      0
      • Chris KawaC Offline
        Chris KawaC Offline
        Chris Kawa
        Lifetime Qt Champion
        wrote on last edited by Chris Kawa
        #5

        Can I force the caller of that method to only use template types/parameters (the T thing) that are const pointers?

        I'll just assume you really meant pointers to const, because const pointer would be LibraryItem* const, which is entirely different beast.

        This is one of those cases where templates come really handy. Here's a stripped down implementation:

        class LibraryMimeData
        {
        private:
            QList<const LibraryItem*> _libraryItems;
        
            // this general type will get rid of non-pointer and pointer to non-const types
            template<typename T, bool is_pointer_to_const> struct Foo {
                static inline QList<T> convert(const QList<const LibraryItem*>& items) = delete;
            };
        
            //the specialized type will only accept pointer to const types
            template<typename T> struct Foo<T, true> {
                static inline QList<T> convert(const QList<const LibraryItem*>& items)
                {
                    return /* DO THE CONVERSION */;
                }
            };
        
        public:
            //and here's a public interface
            template<typename T> QList<T> libraryItems() const {
                return Foo<T, std::is_pointer<T>::value && std::is_const<std::remove_pointer<T>::type>::value>::convert(_libraryItems);
            }
        };
        

        This way it will work for pointer to const types and will give a lovely error about using deleted function for all others.

        kshegunovK 1 Reply Last reply
        5
        • Chris KawaC Chris Kawa

          Can I force the caller of that method to only use template types/parameters (the T thing) that are const pointers?

          I'll just assume you really meant pointers to const, because const pointer would be LibraryItem* const, which is entirely different beast.

          This is one of those cases where templates come really handy. Here's a stripped down implementation:

          class LibraryMimeData
          {
          private:
              QList<const LibraryItem*> _libraryItems;
          
              // this general type will get rid of non-pointer and pointer to non-const types
              template<typename T, bool is_pointer_to_const> struct Foo {
                  static inline QList<T> convert(const QList<const LibraryItem*>& items) = delete;
              };
          
              //the specialized type will only accept pointer to const types
              template<typename T> struct Foo<T, true> {
                  static inline QList<T> convert(const QList<const LibraryItem*>& items)
                  {
                      return /* DO THE CONVERSION */;
                  }
              };
          
          public:
              //and here's a public interface
              template<typename T> QList<T> libraryItems() const {
                  return Foo<T, std::is_pointer<T>::value && std::is_const<std::remove_pointer<T>::type>::value>::convert(_libraryItems);
              }
          };
          

          This way it will work for pointer to const types and will give a lovely error about using deleted function for all others.

          kshegunovK Offline
          kshegunovK Offline
          kshegunov
          Moderators
          wrote on last edited by
          #6

          Ahahah, I needed a couple of reads to get it. It's quite nifty, albeit pretty verbose.

          Read and abide by the Qt Code of Conduct

          1 Reply Last reply
          0
          • Chris KawaC Offline
            Chris KawaC Offline
            Chris Kawa
            Lifetime Qt Champion
            wrote on last edited by
            #7

            @kshegunov Yeah, templates usually do that when it's not you who wrote them ;) I usually steer away from them if I can but when you need to deal with type system and avoid runtime overhead they are a very flexible tool.
            The verbose part is an implementation detail. Commented well and renamed to something better than Foo can live happily in a codebase. The user facing function has a nice clean signature.

            kshegunovK 1 Reply Last reply
            0
            • Chris KawaC Chris Kawa

              @kshegunov Yeah, templates usually do that when it's not you who wrote them ;) I usually steer away from them if I can but when you need to deal with type system and avoid runtime overhead they are a very flexible tool.
              The verbose part is an implementation detail. Commented well and renamed to something better than Foo can live happily in a codebase. The user facing function has a nice clean signature.

              kshegunovK Offline
              kshegunovK Offline
              kshegunov
              Moderators
              wrote on last edited by kshegunov
              #8

              @Chris-Kawa said in Template: Force const parameter:

              I usually steer away from them

              Me too, which you can deduce from my simplistic answer :P
              They're just marginally better than the preprocessor ... code writing code always perplexes me, I must admit ...

              PS.
              I must also give you credit for the partial specialization trick ... never would've come up with it myself.

              Read and abide by the Qt Code of Conduct

              1 Reply Last reply
              0
              • Chris KawaC Offline
                Chris KawaC Offline
                Chris Kawa
                Lifetime Qt Champion
                wrote on last edited by Chris Kawa
                #9

                They're just marginally better than the preprocessor

                Awww, that's hurtful to the templates :) Preprocessor is just glorified find/replace machinery. Templates are a full blown, type safe, statically checked sub-language. Combined with constexpr they really have a Death-Star-like power (with similar caveats ;) )
                I remember when I wrote template based compile time quick sort back in the days. Sure it resulted in a 500Mb executable and crashed the compiler for input arrays larger then a dozen elements but it was constant O(1) time for any input :P
                Sorry for offtopic. Nostalgia took me over ;)

                1 Reply Last reply
                1
                • Joel BodenmannJ Offline
                  Joel BodenmannJ Offline
                  Joel Bodenmann
                  wrote on last edited by
                  #10

                  @Chris-Kawa said in Template: Force const parameter:

                  I'll just assume you really meant pointers to const, because const pointer would be LibraryItem* const, which is entirely different beast.

                  Your assumption is correct. Sorry for using the wrong terminology. I'll blame not-getting-enough-sleep for it :p

                  @Chris-Kawa said in Template: Force const parameter:

                  Here's a stripped down implementation:

                  Oh boy... This is going to take a while (and lots of reading) for me to understand it. But I appreciate your efforts. Also, experience tells me that all code examples you write/post on this forum always just work, so huge Thank you! although I don't understand it yet :p

                  @Chris-Kawa said in Template: Force const parameter:

                  I remember when I wrote template based compile time quick sort back in the days. Sure it resulted in a 500Mb executable and crashed the compiler for input arrays larger then a dozen elements but it was constant O(1) time for any input :P

                  Is there any blog post / white paper you can link to? Sounds interesting :)

                  Industrial process automation software: https://simulton.com
                  Embedded Graphics & GUI library: https://ugfx.io

                  1 Reply Last reply
                  0
                  • Chris KawaC Offline
                    Chris KawaC Offline
                    Chris Kawa
                    Lifetime Qt Champion
                    wrote on last edited by
                    #11

                    I guess the line that need the most explaining is this one:

                    return Foo<T, std::is_pointer<T>::value && std::is_const<std::remove_pointer<T>::type>::value>::convert(_libraryItems);
                    

                    All the std magic is just a verbose way of saying "is T a pointer and does it point to a const value" so it's pretty much
                    Foo<T, true>::convert(_libraryItems) for types that qualify and
                    Foo<T, false>::convert(_libraryItems) for those that don't.

                    Foo<T, false> will call into thet deleted specialization and Foo<T, true> into the real conversion.

                    std::is_pointer<T>::value - this is true for pointers, false for others
                    std::remove_pointer<T>::type - for any given pointer type it's a typedef for the pointed to type e.g for T being int* it's int.
                    std::is_const<X>::value - this is true for const types and false for others

                    Is there any blog post / white paper you can link to? Sounds interesting :)

                    It was a class assignment over a decade ago. I'm sure the topic has a vast coverage, but I can't give you any links because it's simply useless in practice and I hadn't any interest in it after completing it.

                    1 Reply Last reply
                    1
                    • VRoninV Offline
                      VRoninV Offline
                      VRonin
                      wrote on last edited by
                      #12

                      I'm definitely in the wrong section of the forum given my knowledge of the language but why wouldn't a simple static_assert work here?

                      template<class T>
                          QList<T> libraryItems() const
                          {
                      static_assert(std::is_pointer<T>::value && std::is_const<std::remove_pointer<T>::type>::value,"You can only use const pointers as template parameters");
                              QList<T> list;
                      \\ etc
                      

                      "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                      ~Napoleon Bonaparte

                      On a crusade to banish setIndexWidget() from the holy land of Qt

                      1 Reply Last reply
                      2
                      • Chris KawaC Offline
                        Chris KawaC Offline
                        Chris Kawa
                        Lifetime Qt Champion
                        wrote on last edited by
                        #13

                        @VRonin said in Template: Force const parameter:

                        why wouldn't a simple static_assert work here?

                        It definitely would.

                        1 Reply Last reply
                        0

                        • Login

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • Users
                        • Groups
                        • Search
                        • Get Qt Extensions
                        • Unsolved