enum like calculated constants

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
6
down vote

favorite
1












Actually this "problem" feels extremely simple. While doing some calculated icon offsets, i came up with the following approach:



namespace Icons 

struct IconSet
constexpr IconSet(size_t base_offset) noexcept
: base_offset_(base_offset), icon(base_offset * 3), iconSmall(icon + 1), iconBig(icon + 2)

size_t icon;
size_t iconSmall;
size_t iconBig;

size_t base_offset_;

constexpr size_t next() const
return base_offset_ + 1;

;


static constexpr IconSet flower = IconSet(0);
static constexpr IconSet tree = IconSet(flower.next());
static constexpr IconSet forest = IconSet(tree.next());
static constexpr IconSet mountain = IconSet(forest.next());




Now one may write Icons::tree.iconBig for example to get that icons calculated offset. Basicly the designer can change the icons - sometimes adding/removing as well - but always has to provide the entire set (normal, small and big) by convention.



As you see, the issue with this approach is that I had to do that next() function and use it repeatedly - a normal enum wouldn't have this downside.



I know of BOOST_PP and other macro tricks, but I was hoping for something without macro's - since i have a feeling it is not needed and I then sort of would prefer what I already have with the plain next() function.
Another solution would of course just be a normal enum and a calculation function, but that is defeating the purpose of laying it out precalculated.



Hence, I am looking for a simple and portable solution that will give that enum like functionality. It doesn't have to be compile time or constexpr if for example just inline will make it easier.










share|improve this question

























    up vote
    6
    down vote

    favorite
    1












    Actually this "problem" feels extremely simple. While doing some calculated icon offsets, i came up with the following approach:



    namespace Icons 

    struct IconSet
    constexpr IconSet(size_t base_offset) noexcept
    : base_offset_(base_offset), icon(base_offset * 3), iconSmall(icon + 1), iconBig(icon + 2)

    size_t icon;
    size_t iconSmall;
    size_t iconBig;

    size_t base_offset_;

    constexpr size_t next() const
    return base_offset_ + 1;

    ;


    static constexpr IconSet flower = IconSet(0);
    static constexpr IconSet tree = IconSet(flower.next());
    static constexpr IconSet forest = IconSet(tree.next());
    static constexpr IconSet mountain = IconSet(forest.next());




    Now one may write Icons::tree.iconBig for example to get that icons calculated offset. Basicly the designer can change the icons - sometimes adding/removing as well - but always has to provide the entire set (normal, small and big) by convention.



    As you see, the issue with this approach is that I had to do that next() function and use it repeatedly - a normal enum wouldn't have this downside.



    I know of BOOST_PP and other macro tricks, but I was hoping for something without macro's - since i have a feeling it is not needed and I then sort of would prefer what I already have with the plain next() function.
    Another solution would of course just be a normal enum and a calculation function, but that is defeating the purpose of laying it out precalculated.



    Hence, I am looking for a simple and portable solution that will give that enum like functionality. It doesn't have to be compile time or constexpr if for example just inline will make it easier.










    share|improve this question























      up vote
      6
      down vote

      favorite
      1









      up vote
      6
      down vote

      favorite
      1






      1





      Actually this "problem" feels extremely simple. While doing some calculated icon offsets, i came up with the following approach:



      namespace Icons 

      struct IconSet
      constexpr IconSet(size_t base_offset) noexcept
      : base_offset_(base_offset), icon(base_offset * 3), iconSmall(icon + 1), iconBig(icon + 2)

      size_t icon;
      size_t iconSmall;
      size_t iconBig;

      size_t base_offset_;

      constexpr size_t next() const
      return base_offset_ + 1;

      ;


      static constexpr IconSet flower = IconSet(0);
      static constexpr IconSet tree = IconSet(flower.next());
      static constexpr IconSet forest = IconSet(tree.next());
      static constexpr IconSet mountain = IconSet(forest.next());




      Now one may write Icons::tree.iconBig for example to get that icons calculated offset. Basicly the designer can change the icons - sometimes adding/removing as well - but always has to provide the entire set (normal, small and big) by convention.



      As you see, the issue with this approach is that I had to do that next() function and use it repeatedly - a normal enum wouldn't have this downside.



      I know of BOOST_PP and other macro tricks, but I was hoping for something without macro's - since i have a feeling it is not needed and I then sort of would prefer what I already have with the plain next() function.
      Another solution would of course just be a normal enum and a calculation function, but that is defeating the purpose of laying it out precalculated.



      Hence, I am looking for a simple and portable solution that will give that enum like functionality. It doesn't have to be compile time or constexpr if for example just inline will make it easier.










      share|improve this question













      Actually this "problem" feels extremely simple. While doing some calculated icon offsets, i came up with the following approach:



      namespace Icons 

      struct IconSet
      constexpr IconSet(size_t base_offset) noexcept
      : base_offset_(base_offset), icon(base_offset * 3), iconSmall(icon + 1), iconBig(icon + 2)

      size_t icon;
      size_t iconSmall;
      size_t iconBig;

      size_t base_offset_;

      constexpr size_t next() const
      return base_offset_ + 1;

      ;


      static constexpr IconSet flower = IconSet(0);
      static constexpr IconSet tree = IconSet(flower.next());
      static constexpr IconSet forest = IconSet(tree.next());
      static constexpr IconSet mountain = IconSet(forest.next());




      Now one may write Icons::tree.iconBig for example to get that icons calculated offset. Basicly the designer can change the icons - sometimes adding/removing as well - but always has to provide the entire set (normal, small and big) by convention.



      As you see, the issue with this approach is that I had to do that next() function and use it repeatedly - a normal enum wouldn't have this downside.



      I know of BOOST_PP and other macro tricks, but I was hoping for something without macro's - since i have a feeling it is not needed and I then sort of would prefer what I already have with the plain next() function.
      Another solution would of course just be a normal enum and a calculation function, but that is defeating the purpose of laying it out precalculated.



      Hence, I am looking for a simple and portable solution that will give that enum like functionality. It doesn't have to be compile time or constexpr if for example just inline will make it easier.







      c++ c++17 constexpr






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked 2 hours ago









      darune

      540212




      540212






















          2 Answers
          2






          active

          oldest

          votes

















          up vote
          6
          down vote



          accepted










          Here is an approach you can use, based on a fold expression over a compile time integer sequence to instantiate the icons by index. The structured binding gets you individually named non-static, non-constexpr variables.



          The anonymous namespace inside Icons makes those definitions visible in this translation unit only, which you may or may not want.



          Compiler explorer link so you can explore the code options yourself.



          #include <cstddef>
          #include <array>
          #include <utility>

          namespace Icons

          struct IconSet
          constexpr IconSet(size_t base_offset) noexcept
          : base_offset_(base_offset), icon(base_offset * 3), iconSmall(icon + 1), iconBig(icon + 2)

          size_t icon;
          size_t iconSmall;
          size_t iconBig;

          size_t base_offset_;
          ;

          template <std::size_t... Ints>
          constexpr auto make_icons_helper(std::index_sequence<Ints...>) -> std::array<IconSet, sizeof...(Ints)>

          return IconSet(Ints)...;


          template <size_t N>
          constexpr auto make_icons()

          return make_icons_helper(std::make_index_sequence<N>);


          namespace
          auto [flower, tree, forest, mountain] = make_icons<4>();




          int main()

          return Icons::forest.iconSmall;






          share|improve this answer





























            up vote
            2
            down vote













            A simple, non-constexpr solution using a static counter and relying on the fact that static initialization is performed top-to-bottom within a single TU:



            namespace Icons 
            namespace detail_iconSet
            static std::size_t current_base_offset = 0;


            struct IconSet
            IconSet() noexcept
            : base_offset_(detail_iconSet::current_base_offset++)
            , icon(base_offset_ * 3)
            , iconSmall(icon + 1)
            , iconBig(icon + 2)

            std::size_t base_offset_;

            std::size_t icon;
            std::size_t iconSmall;
            std::size_t iconBig;
            ;


            static IconSet flower;
            static IconSet tree;
            static IconSet forest;
            static IconSet mountain;



            See it live on Coliru



            The catch is that this will behave weirdly if you have several headers containing IconSet definitions (i.e. their numbering will change depending on the order of inclusion), but then I don't think there's a way to avoid that.






            share|improve this answer




















            • This will need a big fat comment to point out that it's relying on static initialization order.
              – Max Langhof
              1 hour ago






            • 1




              @MaxLanghof should I put the very first sentence in title font? :p
              – Quentin
              1 hour ago






            • 1




              I didn't mean "your answer fails to mention the fact" but "this is really fragile code and should be very clearly marked as such before going anywhere close to production". ;)
              – Max Langhof
              1 hour ago











            Your Answer






            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "1"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            convertImagesToLinks: true,
            noModals: false,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader:
            brandingHtml: "",
            contentPolicyHtml: "",
            allowUrls: true
            ,
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );













             

            draft saved


            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53079665%2fenum-like-calculated-constants%23new-answer', 'question_page');

            );

            Post as a guest






























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            6
            down vote



            accepted










            Here is an approach you can use, based on a fold expression over a compile time integer sequence to instantiate the icons by index. The structured binding gets you individually named non-static, non-constexpr variables.



            The anonymous namespace inside Icons makes those definitions visible in this translation unit only, which you may or may not want.



            Compiler explorer link so you can explore the code options yourself.



            #include <cstddef>
            #include <array>
            #include <utility>

            namespace Icons

            struct IconSet
            constexpr IconSet(size_t base_offset) noexcept
            : base_offset_(base_offset), icon(base_offset * 3), iconSmall(icon + 1), iconBig(icon + 2)

            size_t icon;
            size_t iconSmall;
            size_t iconBig;

            size_t base_offset_;
            ;

            template <std::size_t... Ints>
            constexpr auto make_icons_helper(std::index_sequence<Ints...>) -> std::array<IconSet, sizeof...(Ints)>

            return IconSet(Ints)...;


            template <size_t N>
            constexpr auto make_icons()

            return make_icons_helper(std::make_index_sequence<N>);


            namespace
            auto [flower, tree, forest, mountain] = make_icons<4>();




            int main()

            return Icons::forest.iconSmall;






            share|improve this answer


























              up vote
              6
              down vote



              accepted










              Here is an approach you can use, based on a fold expression over a compile time integer sequence to instantiate the icons by index. The structured binding gets you individually named non-static, non-constexpr variables.



              The anonymous namespace inside Icons makes those definitions visible in this translation unit only, which you may or may not want.



              Compiler explorer link so you can explore the code options yourself.



              #include <cstddef>
              #include <array>
              #include <utility>

              namespace Icons

              struct IconSet
              constexpr IconSet(size_t base_offset) noexcept
              : base_offset_(base_offset), icon(base_offset * 3), iconSmall(icon + 1), iconBig(icon + 2)

              size_t icon;
              size_t iconSmall;
              size_t iconBig;

              size_t base_offset_;
              ;

              template <std::size_t... Ints>
              constexpr auto make_icons_helper(std::index_sequence<Ints...>) -> std::array<IconSet, sizeof...(Ints)>

              return IconSet(Ints)...;


              template <size_t N>
              constexpr auto make_icons()

              return make_icons_helper(std::make_index_sequence<N>);


              namespace
              auto [flower, tree, forest, mountain] = make_icons<4>();




              int main()

              return Icons::forest.iconSmall;






              share|improve this answer
























                up vote
                6
                down vote



                accepted







                up vote
                6
                down vote



                accepted






                Here is an approach you can use, based on a fold expression over a compile time integer sequence to instantiate the icons by index. The structured binding gets you individually named non-static, non-constexpr variables.



                The anonymous namespace inside Icons makes those definitions visible in this translation unit only, which you may or may not want.



                Compiler explorer link so you can explore the code options yourself.



                #include <cstddef>
                #include <array>
                #include <utility>

                namespace Icons

                struct IconSet
                constexpr IconSet(size_t base_offset) noexcept
                : base_offset_(base_offset), icon(base_offset * 3), iconSmall(icon + 1), iconBig(icon + 2)

                size_t icon;
                size_t iconSmall;
                size_t iconBig;

                size_t base_offset_;
                ;

                template <std::size_t... Ints>
                constexpr auto make_icons_helper(std::index_sequence<Ints...>) -> std::array<IconSet, sizeof...(Ints)>

                return IconSet(Ints)...;


                template <size_t N>
                constexpr auto make_icons()

                return make_icons_helper(std::make_index_sequence<N>);


                namespace
                auto [flower, tree, forest, mountain] = make_icons<4>();




                int main()

                return Icons::forest.iconSmall;






                share|improve this answer














                Here is an approach you can use, based on a fold expression over a compile time integer sequence to instantiate the icons by index. The structured binding gets you individually named non-static, non-constexpr variables.



                The anonymous namespace inside Icons makes those definitions visible in this translation unit only, which you may or may not want.



                Compiler explorer link so you can explore the code options yourself.



                #include <cstddef>
                #include <array>
                #include <utility>

                namespace Icons

                struct IconSet
                constexpr IconSet(size_t base_offset) noexcept
                : base_offset_(base_offset), icon(base_offset * 3), iconSmall(icon + 1), iconBig(icon + 2)

                size_t icon;
                size_t iconSmall;
                size_t iconBig;

                size_t base_offset_;
                ;

                template <std::size_t... Ints>
                constexpr auto make_icons_helper(std::index_sequence<Ints...>) -> std::array<IconSet, sizeof...(Ints)>

                return IconSet(Ints)...;


                template <size_t N>
                constexpr auto make_icons()

                return make_icons_helper(std::make_index_sequence<N>);


                namespace
                auto [flower, tree, forest, mountain] = make_icons<4>();




                int main()

                return Icons::forest.iconSmall;







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited 2 hours ago

























                answered 2 hours ago









                Bruce Collie

                3435




                3435






















                    up vote
                    2
                    down vote













                    A simple, non-constexpr solution using a static counter and relying on the fact that static initialization is performed top-to-bottom within a single TU:



                    namespace Icons 
                    namespace detail_iconSet
                    static std::size_t current_base_offset = 0;


                    struct IconSet
                    IconSet() noexcept
                    : base_offset_(detail_iconSet::current_base_offset++)
                    , icon(base_offset_ * 3)
                    , iconSmall(icon + 1)
                    , iconBig(icon + 2)

                    std::size_t base_offset_;

                    std::size_t icon;
                    std::size_t iconSmall;
                    std::size_t iconBig;
                    ;


                    static IconSet flower;
                    static IconSet tree;
                    static IconSet forest;
                    static IconSet mountain;



                    See it live on Coliru



                    The catch is that this will behave weirdly if you have several headers containing IconSet definitions (i.e. their numbering will change depending on the order of inclusion), but then I don't think there's a way to avoid that.






                    share|improve this answer




















                    • This will need a big fat comment to point out that it's relying on static initialization order.
                      – Max Langhof
                      1 hour ago






                    • 1




                      @MaxLanghof should I put the very first sentence in title font? :p
                      – Quentin
                      1 hour ago






                    • 1




                      I didn't mean "your answer fails to mention the fact" but "this is really fragile code and should be very clearly marked as such before going anywhere close to production". ;)
                      – Max Langhof
                      1 hour ago















                    up vote
                    2
                    down vote













                    A simple, non-constexpr solution using a static counter and relying on the fact that static initialization is performed top-to-bottom within a single TU:



                    namespace Icons 
                    namespace detail_iconSet
                    static std::size_t current_base_offset = 0;


                    struct IconSet
                    IconSet() noexcept
                    : base_offset_(detail_iconSet::current_base_offset++)
                    , icon(base_offset_ * 3)
                    , iconSmall(icon + 1)
                    , iconBig(icon + 2)

                    std::size_t base_offset_;

                    std::size_t icon;
                    std::size_t iconSmall;
                    std::size_t iconBig;
                    ;


                    static IconSet flower;
                    static IconSet tree;
                    static IconSet forest;
                    static IconSet mountain;



                    See it live on Coliru



                    The catch is that this will behave weirdly if you have several headers containing IconSet definitions (i.e. their numbering will change depending on the order of inclusion), but then I don't think there's a way to avoid that.






                    share|improve this answer




















                    • This will need a big fat comment to point out that it's relying on static initialization order.
                      – Max Langhof
                      1 hour ago






                    • 1




                      @MaxLanghof should I put the very first sentence in title font? :p
                      – Quentin
                      1 hour ago






                    • 1




                      I didn't mean "your answer fails to mention the fact" but "this is really fragile code and should be very clearly marked as such before going anywhere close to production". ;)
                      – Max Langhof
                      1 hour ago













                    up vote
                    2
                    down vote










                    up vote
                    2
                    down vote









                    A simple, non-constexpr solution using a static counter and relying on the fact that static initialization is performed top-to-bottom within a single TU:



                    namespace Icons 
                    namespace detail_iconSet
                    static std::size_t current_base_offset = 0;


                    struct IconSet
                    IconSet() noexcept
                    : base_offset_(detail_iconSet::current_base_offset++)
                    , icon(base_offset_ * 3)
                    , iconSmall(icon + 1)
                    , iconBig(icon + 2)

                    std::size_t base_offset_;

                    std::size_t icon;
                    std::size_t iconSmall;
                    std::size_t iconBig;
                    ;


                    static IconSet flower;
                    static IconSet tree;
                    static IconSet forest;
                    static IconSet mountain;



                    See it live on Coliru



                    The catch is that this will behave weirdly if you have several headers containing IconSet definitions (i.e. their numbering will change depending on the order of inclusion), but then I don't think there's a way to avoid that.






                    share|improve this answer












                    A simple, non-constexpr solution using a static counter and relying on the fact that static initialization is performed top-to-bottom within a single TU:



                    namespace Icons 
                    namespace detail_iconSet
                    static std::size_t current_base_offset = 0;


                    struct IconSet
                    IconSet() noexcept
                    : base_offset_(detail_iconSet::current_base_offset++)
                    , icon(base_offset_ * 3)
                    , iconSmall(icon + 1)
                    , iconBig(icon + 2)

                    std::size_t base_offset_;

                    std::size_t icon;
                    std::size_t iconSmall;
                    std::size_t iconBig;
                    ;


                    static IconSet flower;
                    static IconSet tree;
                    static IconSet forest;
                    static IconSet mountain;



                    See it live on Coliru



                    The catch is that this will behave weirdly if you have several headers containing IconSet definitions (i.e. their numbering will change depending on the order of inclusion), but then I don't think there's a way to avoid that.







                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered 2 hours ago









                    Quentin

                    42.5k575130




                    42.5k575130











                    • This will need a big fat comment to point out that it's relying on static initialization order.
                      – Max Langhof
                      1 hour ago






                    • 1




                      @MaxLanghof should I put the very first sentence in title font? :p
                      – Quentin
                      1 hour ago






                    • 1




                      I didn't mean "your answer fails to mention the fact" but "this is really fragile code and should be very clearly marked as such before going anywhere close to production". ;)
                      – Max Langhof
                      1 hour ago

















                    • This will need a big fat comment to point out that it's relying on static initialization order.
                      – Max Langhof
                      1 hour ago






                    • 1




                      @MaxLanghof should I put the very first sentence in title font? :p
                      – Quentin
                      1 hour ago






                    • 1




                      I didn't mean "your answer fails to mention the fact" but "this is really fragile code and should be very clearly marked as such before going anywhere close to production". ;)
                      – Max Langhof
                      1 hour ago
















                    This will need a big fat comment to point out that it's relying on static initialization order.
                    – Max Langhof
                    1 hour ago




                    This will need a big fat comment to point out that it's relying on static initialization order.
                    – Max Langhof
                    1 hour ago




                    1




                    1




                    @MaxLanghof should I put the very first sentence in title font? :p
                    – Quentin
                    1 hour ago




                    @MaxLanghof should I put the very first sentence in title font? :p
                    – Quentin
                    1 hour ago




                    1




                    1




                    I didn't mean "your answer fails to mention the fact" but "this is really fragile code and should be very clearly marked as such before going anywhere close to production". ;)
                    – Max Langhof
                    1 hour ago





                    I didn't mean "your answer fails to mention the fact" but "this is really fragile code and should be very clearly marked as such before going anywhere close to production". ;)
                    – Max Langhof
                    1 hour ago


















                     

                    draft saved


                    draft discarded















































                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53079665%2fenum-like-calculated-constants%23new-answer', 'question_page');

                    );

                    Post as a guest













































































                    Comments

                    Popular posts from this blog

                    What does second last employer means? [closed]

                    List of Gilmore Girls characters

                    Confectionery