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 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