Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Not a question, just a lament about metaprogramming

Not a question, just a lament about metaprogramming

Scheduled Pinned Locked Moved C / C++ / MFC
c++graphicsdesigncomgame-dev
8 Posts 2 Posters 4 Views 1 Watching
  • 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.
  • H Offline
    H Offline
    honey the codewitch
    wrote on last edited by
    #1

    I love C++ because I can do things like this:

    // creates a BGRx pixel by making each channel
    // one quarter of the whole. Any remainder bits
    // are added to the green channel. One channel
    // is unused. Consumed by DirectX
    template
    using bgrx_pixel = gfx::pixel<
    gfx::channel_traits,
    gfx::channel_traits,
    gfx::channel_traits,
    gfx::channel_traits

    ;
    using screen_t = uix::screen>;

    Now, I've made pixels definable in terms of their memory footprint and what channels they expose, like R, G and B, or C, Y, and Mk or whatever. Above I'm defining a BGRx8888 pixel which DirectX uses for its surfaces. That's 3 8-bit channels with a fourth unused, blue first. The above code is facilitated by this: gfx/include/gfx_pixel.hpp at master · codewitch-honey-crisis/gfx · GitHub[^] That defines things like channel traits, and does all the necessary compile time computations to make it work. The problem is this: It's write-only code, and there's no easy way to remedy it because meta-programming in C++17 and prior is very hackish. C++20 and beyond improve the situation a little, but the heavy reliance on The STL rather than language improvements to facilitate this leaves me wanting on little embedded platforms where the STL might not be complete or even available. It's cool that with C++ you can even make facilities to enable code like the above, and it's the only language I know of that allows for it, but I really wish there was a cleaner way to do this stuff. :~

    Check out my IoT graphics library here: https://honeythecodewitch.com/gfx And my IoT UI/User Experience library here: https://honeythecodewitch.com/uix

    J 1 Reply Last reply
    0
    • H honey the codewitch

      I love C++ because I can do things like this:

      // creates a BGRx pixel by making each channel
      // one quarter of the whole. Any remainder bits
      // are added to the green channel. One channel
      // is unused. Consumed by DirectX
      template
      using bgrx_pixel = gfx::pixel<
      gfx::channel_traits,
      gfx::channel_traits,
      gfx::channel_traits,
      gfx::channel_traits

      ;
      using screen_t = uix::screen>;

      Now, I've made pixels definable in terms of their memory footprint and what channels they expose, like R, G and B, or C, Y, and Mk or whatever. Above I'm defining a BGRx8888 pixel which DirectX uses for its surfaces. That's 3 8-bit channels with a fourth unused, blue first. The above code is facilitated by this: gfx/include/gfx_pixel.hpp at master · codewitch-honey-crisis/gfx · GitHub[^] That defines things like channel traits, and does all the necessary compile time computations to make it work. The problem is this: It's write-only code, and there's no easy way to remedy it because meta-programming in C++17 and prior is very hackish. C++20 and beyond improve the situation a little, but the heavy reliance on The STL rather than language improvements to facilitate this leaves me wanting on little embedded platforms where the STL might not be complete or even available. It's cool that with C++ you can even make facilities to enable code like the above, and it's the only language I know of that allows for it, but I really wish there was a cleaner way to do this stuff. :~

      Check out my IoT graphics library here: https://honeythecodewitch.com/gfx And my IoT UI/User Experience library here: https://honeythecodewitch.com/uix

      J Offline
      J Offline
      jschell
      wrote on last edited by
      #2

      honey the codewitch wrote:

      there was a cleaner way to do this stuff

      I give up...why is this specific bit of code better as a template versus a method? To me a method would be cleaner. And it would allow you to do what you want.

      H 2 Replies Last reply
      0
      • J jschell

        honey the codewitch wrote:

        there was a cleaner way to do this stuff

        I give up...why is this specific bit of code better as a template versus a method? To me a method would be cleaner. And it would allow you to do what you want.

        H Offline
        H Offline
        honey the codewitch
        wrote on last edited by
        #3

        A method would precompute the arbitrary bitshifts needed to craft a bitmap with the appropriate binary footprint, set individual arbitrary color channels, etc, at compile time? AFAIK a method cannot define a type. constexpr won't do that. It must be some C++20 or beyond feature I'm not aware of, but to solve this problem in C++17 requires a template.

        Check out my IoT graphics library here: https://honeythecodewitch.com/gfx And my IoT UI/User Experience library here: https://honeythecodewitch.com/uix

        J 1 Reply Last reply
        0
        • J jschell

          honey the codewitch wrote:

          there was a cleaner way to do this stuff

          I give up...why is this specific bit of code better as a template versus a method? To me a method would be cleaner. And it would allow you to do what you want.

          H Offline
          H Offline
          honey the codewitch
          wrote on last edited by
          #4

          Forgive the multiple replies but I think maybe I'm not explaining the above. That is user code in the OP. That defines a pixel type that DirectX can consume. There are others. I've pasted a swath of additional definitions for other types of pixels that are commonly used in my library. You can then take a pixel type and do like this using fb_t = bitmap>; uint8_t fb_buffer[fb_t::sizeof_buffer(screen_size)]; fb_t fb(screen_size,fb_buffer); Then when you proceed to draw to fb it's begin() method (pointing to fb_buffer in this case) contains bitmap data of that format based on the definition in the OP. If it was an 18 bit pixel, as some weird graphics devices support, it would do that too. They aren't necessarily even on clean byte boundaries. Forgive the following, but hopefully it provides useful context

          // creates an RGB pixel by making each channel
          // one third of the whole. Any remainder bits
          // are added to the green channel
          template
          using rgb_pixel = pixel<
          channel_traits,
          channel_traits,
          channel_traits
          >;
          // creates an RGBA pixel by making each channel
          // one quarter of the whole. Any remainder bits
          // are added to the green channel
          template
          using rgba_pixel = pixel<
          channel_traits,
          channel_traits,
          channel_traits,
          channel_traits
          >;
          // creates a grayscale or monochome pixel
          template
          using gsc_pixel = pixel<
          channel_traits
          >;
          // creates a Y'UV pixel by making each channel
          // one third of the whole. Any remainder bits
          // are added to the Y' channel
          template
          using yuv_pixel = pixel<
          channel_traits,
          channel_traits,
          channel_traits
          >;
          // creates a Y'UV/A pixel by making each
          // channel 1/4 of the whole. Remaining bits
          // are added to Y'
          template
          using yuva_pixel = pixel<
          channel_traits

          1 Reply Last reply
          0
          • H honey the codewitch

            A method would precompute the arbitrary bitshifts needed to craft a bitmap with the appropriate binary footprint, set individual arbitrary color channels, etc, at compile time? AFAIK a method cannot define a type. constexpr won't do that. It must be some C++20 or beyond feature I'm not aware of, but to solve this problem in C++17 requires a template.

            Check out my IoT graphics library here: https://honeythecodewitch.com/gfx And my IoT UI/User Experience library here: https://honeythecodewitch.com/uix

            J Offline
            J Offline
            jschell
            wrote on last edited by
            #5

            honey the codewitch wrote:

            It must be some C++20 or beyond feature I'm not aware of

            Not at all. So you want to use certain fixed values in your code, but you don't want to compute them (presumably manually.) So write an executable that outputs those values as code statements. I suspect 1. That executable (the code) is more obvious in its purpose 2. It can be modified to do the part that you claim is missing. 3. It will make the target code less confusing. You can even make the execution of that executable part of your build process.

            H 1 Reply Last reply
            0
            • J jschell

              honey the codewitch wrote:

              It must be some C++20 or beyond feature I'm not aware of

              Not at all. So you want to use certain fixed values in your code, but you don't want to compute them (presumably manually.) So write an executable that outputs those values as code statements. I suspect 1. That executable (the code) is more obvious in its purpose 2. It can be modified to do the part that you claim is missing. 3. It will make the target code less confusing. You can even make the execution of that executable part of your build process.

              H Offline
              H Offline
              honey the codewitch
              wrote on last edited by
              #6

              I'm not using a code generator. C++ already has one built in. It's called template and that's literally what it's designed to do. Anyway, I'd rather deal with it's weirdness than write code generators for everything, at which point I'd just use C because template and constexpr are the only reason I care about C++ over C.

              Check out my IoT graphics library here: https://honeythecodewitch.com/gfx And my IoT UI/User Experience library here: https://honeythecodewitch.com/uix

              J 1 Reply Last reply
              0
              • H honey the codewitch

                I'm not using a code generator. C++ already has one built in. It's called template and that's literally what it's designed to do. Anyway, I'd rather deal with it's weirdness than write code generators for everything, at which point I'd just use C because template and constexpr are the only reason I care about C++ over C.

                Check out my IoT graphics library here: https://honeythecodewitch.com/gfx And my IoT UI/User Experience library here: https://honeythecodewitch.com/uix

                J Offline
                J Offline
                jschell
                wrote on last edited by
                #7

                honey the codewitch wrote:

                I'm not using a code generator. C++ already has one built in. It's called template and that's literally what it's designed to do.

                Rather certain that is not why they were specifically added to the language. The fact that you can do that is ok. Just not what they exist for. Following agrees with my understanding of the addition. Template (C++) - Wikipedia[^] "Major inspirations for C++ templates were the parameterized module"

                honey the codewitch wrote:

                I'd rather deal with it's weirdness than write code generators for everything

                One case doesn't mean you would need to to it for all. And your lament is that it does not have all the functionality you would like for this specific situation. So you can hack around it or find another solution.

                honey the codewitch wrote:

                Anyway, I'd rather deal

                Again this is another difference in domain spaces. Maintenance for you is based on what you do because that is the business model that you have created. For me I must consider how others will maintain what I have created. So for complex solutions I must consider the totality of what some future developer might be dealing with when they look at my code. So I would consider a one off module as being more understandable rather than perhaps several different code paths to work around to a potential solution.

                H 1 Reply Last reply
                0
                • J jschell

                  honey the codewitch wrote:

                  I'm not using a code generator. C++ already has one built in. It's called template and that's literally what it's designed to do.

                  Rather certain that is not why they were specifically added to the language. The fact that you can do that is ok. Just not what they exist for. Following agrees with my understanding of the addition. Template (C++) - Wikipedia[^] "Major inspirations for C++ templates were the parameterized module"

                  honey the codewitch wrote:

                  I'd rather deal with it's weirdness than write code generators for everything

                  One case doesn't mean you would need to to it for all. And your lament is that it does not have all the functionality you would like for this specific situation. So you can hack around it or find another solution.

                  honey the codewitch wrote:

                  Anyway, I'd rather deal

                  Again this is another difference in domain spaces. Maintenance for you is based on what you do because that is the business model that you have created. For me I must consider how others will maintain what I have created. So for complex solutions I must consider the totality of what some future developer might be dealing with when they look at my code. So I would consider a one off module as being more understandable rather than perhaps several different code paths to work around to a potential solution.

                  H Offline
                  H Offline
                  honey the codewitch
                  wrote on last edited by
                  #8

                  I do use code generation where template won't suffice, like generating state machines, but it complicates the build process. In the end metaprogramming evolved from simple GP without intrinsic language support for it and that is ultimately what I'm complaining about. Newer iterations of C++ post say 20 are starting to rectify this, and make the concepts more "first class" That will improve readability without complicating the build.

                  Check out my IoT graphics library here: https://honeythecodewitch.com/gfx And my IoT UI/User Experience library here: https://honeythecodewitch.com/uix

                  1 Reply Last reply
                  0
                  Reply
                  • Reply as topic
                  Log in to reply
                  • Oldest to Newest
                  • Newest to Oldest
                  • Most Votes


                  • Login

                  • Don't have an account? Register

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • World
                  • Users
                  • Groups