C++ initialization of array of tuple's without boilerplate












0












$begingroup$


Regarding an application written in C++ using the Windows API. I'd like to store a user setting like the window position on program exit, to the Windows registry and retrieve settings like these on the next start of the program.



I currently have 3 settings to be stored/retrieved to/from the registry.



typedef struct tagWINPOS
{
DWORD dwWindowStyle;
int iWindowX;
int iWindowY;
} winpos_t;

HKEY hKeyApp = (HKEY)INVALID_HANDLE_VALUE;
const char szWindowStyle = "WindowStyle";
const char szWindowX = "WindowX";
const char szWindowY = "WindowY";


Later on in the code I'm calling functions like RegSetValueEx and RegQueryValueEx always three times. Like so:



int SaveSettings( HWND hWnd )
{
winpos_t wpos;
// window dimensions from hWnd are stored to wpos, not shown

RegSetValueEx( hKeyApp, szWindowStyle, 0,
REG_DWORD,
(const BYTE*)&wpos.dwWindowStyle,
sizeof(wpos.dwWindowStyle) );
RegSetValueEx( hKeyApp, szWindowX, 0,
REG_DWORD,
(const BYTE*)&wpos.iWindowX,
sizeof(wpos.iWindowX) );
RegSetValueEx( hKeyApp, szWindowY, 0,
REG_DWORD,
(const BYTE*)&wpos.iWindowY,
sizeof(wpos.iWindowY) );

// further irrelevant code removed
}


Things start to look a bit tedious. So I was thinking to put all the parameters for one function call (say RegSetValueEx) into an std::array and then make a for loop iterating over all the array elements.



Because the Windows registry can store multiple data types, like DWORD (32-bit), QWORD (64-bit) and strings. I thought about std::variant to list all of these for this data field.



I'm started with a little test program like this:



#include <cstddef>
#include <cstdio>
#include <cstdint>
#include <tuple>
#include <variant>

typedef std::variant< int32_t, int64_t, char* > data_t;

typedef std::tuple<
data_t, // setting data
const char*, // setting name
std::size_t // size of setting [bytes]
> setting_t;

typedef std::array< setting_t, 2 > settings_t;

constexpr int reg_dword = 0;
constexpr int reg_qword = 1;

constexpr settings_t settings{
std::make_tuple( (std::in_place_index<reg_dword>, 33), "Mydata", 4 ),
std::make_tuple( (std::in_place_index<reg_qword>, 34), "Mydata2", sizeof(std::in_place_index_t<reg_qword>) ) };

int main()
{
printf( "name: %s, value %ldn", std::get<1>( settings[0] ), std::get<0>( std::get<0>( settings[0] ) ));

getchar();
return EXIT_SUCCESS;
}


Anyway, do people consider this approach a good one to get to my goal of having to spell out a single function call of RegSetValueEx inside a for loop?



The initialization of the array has much boilerplate as well as the effort to obtain values. What is a good approach to improve the readability of this? Maybe a constexpr function like std::make_tuple but then more specific for my case?










share|improve this question







New contributor




Zeyneb is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







$endgroup$

















    0












    $begingroup$


    Regarding an application written in C++ using the Windows API. I'd like to store a user setting like the window position on program exit, to the Windows registry and retrieve settings like these on the next start of the program.



    I currently have 3 settings to be stored/retrieved to/from the registry.



    typedef struct tagWINPOS
    {
    DWORD dwWindowStyle;
    int iWindowX;
    int iWindowY;
    } winpos_t;

    HKEY hKeyApp = (HKEY)INVALID_HANDLE_VALUE;
    const char szWindowStyle = "WindowStyle";
    const char szWindowX = "WindowX";
    const char szWindowY = "WindowY";


    Later on in the code I'm calling functions like RegSetValueEx and RegQueryValueEx always three times. Like so:



    int SaveSettings( HWND hWnd )
    {
    winpos_t wpos;
    // window dimensions from hWnd are stored to wpos, not shown

    RegSetValueEx( hKeyApp, szWindowStyle, 0,
    REG_DWORD,
    (const BYTE*)&wpos.dwWindowStyle,
    sizeof(wpos.dwWindowStyle) );
    RegSetValueEx( hKeyApp, szWindowX, 0,
    REG_DWORD,
    (const BYTE*)&wpos.iWindowX,
    sizeof(wpos.iWindowX) );
    RegSetValueEx( hKeyApp, szWindowY, 0,
    REG_DWORD,
    (const BYTE*)&wpos.iWindowY,
    sizeof(wpos.iWindowY) );

    // further irrelevant code removed
    }


    Things start to look a bit tedious. So I was thinking to put all the parameters for one function call (say RegSetValueEx) into an std::array and then make a for loop iterating over all the array elements.



    Because the Windows registry can store multiple data types, like DWORD (32-bit), QWORD (64-bit) and strings. I thought about std::variant to list all of these for this data field.



    I'm started with a little test program like this:



    #include <cstddef>
    #include <cstdio>
    #include <cstdint>
    #include <tuple>
    #include <variant>

    typedef std::variant< int32_t, int64_t, char* > data_t;

    typedef std::tuple<
    data_t, // setting data
    const char*, // setting name
    std::size_t // size of setting [bytes]
    > setting_t;

    typedef std::array< setting_t, 2 > settings_t;

    constexpr int reg_dword = 0;
    constexpr int reg_qword = 1;

    constexpr settings_t settings{
    std::make_tuple( (std::in_place_index<reg_dword>, 33), "Mydata", 4 ),
    std::make_tuple( (std::in_place_index<reg_qword>, 34), "Mydata2", sizeof(std::in_place_index_t<reg_qword>) ) };

    int main()
    {
    printf( "name: %s, value %ldn", std::get<1>( settings[0] ), std::get<0>( std::get<0>( settings[0] ) ));

    getchar();
    return EXIT_SUCCESS;
    }


    Anyway, do people consider this approach a good one to get to my goal of having to spell out a single function call of RegSetValueEx inside a for loop?



    The initialization of the array has much boilerplate as well as the effort to obtain values. What is a good approach to improve the readability of this? Maybe a constexpr function like std::make_tuple but then more specific for my case?










    share|improve this question







    New contributor




    Zeyneb is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.







    $endgroup$















      0












      0








      0





      $begingroup$


      Regarding an application written in C++ using the Windows API. I'd like to store a user setting like the window position on program exit, to the Windows registry and retrieve settings like these on the next start of the program.



      I currently have 3 settings to be stored/retrieved to/from the registry.



      typedef struct tagWINPOS
      {
      DWORD dwWindowStyle;
      int iWindowX;
      int iWindowY;
      } winpos_t;

      HKEY hKeyApp = (HKEY)INVALID_HANDLE_VALUE;
      const char szWindowStyle = "WindowStyle";
      const char szWindowX = "WindowX";
      const char szWindowY = "WindowY";


      Later on in the code I'm calling functions like RegSetValueEx and RegQueryValueEx always three times. Like so:



      int SaveSettings( HWND hWnd )
      {
      winpos_t wpos;
      // window dimensions from hWnd are stored to wpos, not shown

      RegSetValueEx( hKeyApp, szWindowStyle, 0,
      REG_DWORD,
      (const BYTE*)&wpos.dwWindowStyle,
      sizeof(wpos.dwWindowStyle) );
      RegSetValueEx( hKeyApp, szWindowX, 0,
      REG_DWORD,
      (const BYTE*)&wpos.iWindowX,
      sizeof(wpos.iWindowX) );
      RegSetValueEx( hKeyApp, szWindowY, 0,
      REG_DWORD,
      (const BYTE*)&wpos.iWindowY,
      sizeof(wpos.iWindowY) );

      // further irrelevant code removed
      }


      Things start to look a bit tedious. So I was thinking to put all the parameters for one function call (say RegSetValueEx) into an std::array and then make a for loop iterating over all the array elements.



      Because the Windows registry can store multiple data types, like DWORD (32-bit), QWORD (64-bit) and strings. I thought about std::variant to list all of these for this data field.



      I'm started with a little test program like this:



      #include <cstddef>
      #include <cstdio>
      #include <cstdint>
      #include <tuple>
      #include <variant>

      typedef std::variant< int32_t, int64_t, char* > data_t;

      typedef std::tuple<
      data_t, // setting data
      const char*, // setting name
      std::size_t // size of setting [bytes]
      > setting_t;

      typedef std::array< setting_t, 2 > settings_t;

      constexpr int reg_dword = 0;
      constexpr int reg_qword = 1;

      constexpr settings_t settings{
      std::make_tuple( (std::in_place_index<reg_dword>, 33), "Mydata", 4 ),
      std::make_tuple( (std::in_place_index<reg_qword>, 34), "Mydata2", sizeof(std::in_place_index_t<reg_qword>) ) };

      int main()
      {
      printf( "name: %s, value %ldn", std::get<1>( settings[0] ), std::get<0>( std::get<0>( settings[0] ) ));

      getchar();
      return EXIT_SUCCESS;
      }


      Anyway, do people consider this approach a good one to get to my goal of having to spell out a single function call of RegSetValueEx inside a for loop?



      The initialization of the array has much boilerplate as well as the effort to obtain values. What is a good approach to improve the readability of this? Maybe a constexpr function like std::make_tuple but then more specific for my case?










      share|improve this question







      New contributor




      Zeyneb is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.







      $endgroup$




      Regarding an application written in C++ using the Windows API. I'd like to store a user setting like the window position on program exit, to the Windows registry and retrieve settings like these on the next start of the program.



      I currently have 3 settings to be stored/retrieved to/from the registry.



      typedef struct tagWINPOS
      {
      DWORD dwWindowStyle;
      int iWindowX;
      int iWindowY;
      } winpos_t;

      HKEY hKeyApp = (HKEY)INVALID_HANDLE_VALUE;
      const char szWindowStyle = "WindowStyle";
      const char szWindowX = "WindowX";
      const char szWindowY = "WindowY";


      Later on in the code I'm calling functions like RegSetValueEx and RegQueryValueEx always three times. Like so:



      int SaveSettings( HWND hWnd )
      {
      winpos_t wpos;
      // window dimensions from hWnd are stored to wpos, not shown

      RegSetValueEx( hKeyApp, szWindowStyle, 0,
      REG_DWORD,
      (const BYTE*)&wpos.dwWindowStyle,
      sizeof(wpos.dwWindowStyle) );
      RegSetValueEx( hKeyApp, szWindowX, 0,
      REG_DWORD,
      (const BYTE*)&wpos.iWindowX,
      sizeof(wpos.iWindowX) );
      RegSetValueEx( hKeyApp, szWindowY, 0,
      REG_DWORD,
      (const BYTE*)&wpos.iWindowY,
      sizeof(wpos.iWindowY) );

      // further irrelevant code removed
      }


      Things start to look a bit tedious. So I was thinking to put all the parameters for one function call (say RegSetValueEx) into an std::array and then make a for loop iterating over all the array elements.



      Because the Windows registry can store multiple data types, like DWORD (32-bit), QWORD (64-bit) and strings. I thought about std::variant to list all of these for this data field.



      I'm started with a little test program like this:



      #include <cstddef>
      #include <cstdio>
      #include <cstdint>
      #include <tuple>
      #include <variant>

      typedef std::variant< int32_t, int64_t, char* > data_t;

      typedef std::tuple<
      data_t, // setting data
      const char*, // setting name
      std::size_t // size of setting [bytes]
      > setting_t;

      typedef std::array< setting_t, 2 > settings_t;

      constexpr int reg_dword = 0;
      constexpr int reg_qword = 1;

      constexpr settings_t settings{
      std::make_tuple( (std::in_place_index<reg_dword>, 33), "Mydata", 4 ),
      std::make_tuple( (std::in_place_index<reg_qword>, 34), "Mydata2", sizeof(std::in_place_index_t<reg_qword>) ) };

      int main()
      {
      printf( "name: %s, value %ldn", std::get<1>( settings[0] ), std::get<0>( std::get<0>( settings[0] ) ));

      getchar();
      return EXIT_SUCCESS;
      }


      Anyway, do people consider this approach a good one to get to my goal of having to spell out a single function call of RegSetValueEx inside a for loop?



      The initialization of the array has much boilerplate as well as the effort to obtain values. What is a good approach to improve the readability of this? Maybe a constexpr function like std::make_tuple but then more specific for my case?







      c++ array c++17






      share|improve this question







      New contributor




      Zeyneb is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.











      share|improve this question







      New contributor




      Zeyneb is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      share|improve this question




      share|improve this question






      New contributor




      Zeyneb is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      asked 40 mins ago









      ZeynebZeyneb

      1




      1




      New contributor




      Zeyneb is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.





      New contributor





      Zeyneb is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






      Zeyneb is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






















          0






          active

          oldest

          votes











          Your Answer





          StackExchange.ifUsing("editor", function () {
          return StackExchange.using("mathjaxEditing", function () {
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          });
          });
          }, "mathjax-editing");

          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: "196"
          };
          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',
          autoActivateHeartbeat: false,
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });






          Zeyneb is a new contributor. Be nice, and check out our Code of Conduct.










          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f212891%2fc-initialization-of-array-of-tuples-without-boilerplate%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          0






          active

          oldest

          votes








          0






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          Zeyneb is a new contributor. Be nice, and check out our Code of Conduct.










          draft saved

          draft discarded


















          Zeyneb is a new contributor. Be nice, and check out our Code of Conduct.













          Zeyneb is a new contributor. Be nice, and check out our Code of Conduct.












          Zeyneb is a new contributor. Be nice, and check out our Code of Conduct.
















          Thanks for contributing an answer to Code Review Stack Exchange!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          Use MathJax to format equations. MathJax reference.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f212891%2fc-initialization-of-array-of-tuples-without-boilerplate%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Сан-Квентин

          Алькесар

          Josef Freinademetz