noexcept visitation for std::variant












3














For some standard library classes, access to parts of their contents may legitimately fail. Usually you have the choice between some potentially throwing method an one that is marked noexcept. The latter spares the check on the precondition, so if you want to take the responsibility yourself, you can. This can be used under circumstances where using exceptions are not permitted or when fixing a performance bottleneck.



Example 1: std::vector element access:



std::vector<int> vec;
vec.at(n) // throws std::out_of_range
vec[n] // potentially UB, thus your own responsibility


Example 2: std::optional access:



std::optional<int> optn;
optn.value() // throws std::bad_optional_access
*optn // potentially UB, thus your own responsibility


Now on to std::variant. Directly accessing an alternative somewhat follows this pattern:



std::variant<std::string, int> var;
std::get<int>(var) // potentially throwing std::bad_variant_access
*std::get_if<int>(&var) // potentially UB, thus your own responsibility


But this time the signature changes, we have to inject * and &. The downside of this is that we don't get automatic move semantics. One more thing to keep in your mind...



But it gets worse if you have a look at std::visit(Visitor&& vis, Variants&&... vars). There is no noexcept alternative for it, although it only throws




if any variant in vars is valueless_by_exception.




This means for visiting variants you cannot choose to take the responsibility yourself, and if you have no choice and must avoid exceptions, you cannot visit std::variants at all with standard tooling! (apart from the terrible workaround of switching on variant::index())



To me, this looks like a pretty bad design oversight... or there a reason for this? And in case I'm right about the oversight, is there an initiative to fix this in the standard?










share|improve this question



























    3














    For some standard library classes, access to parts of their contents may legitimately fail. Usually you have the choice between some potentially throwing method an one that is marked noexcept. The latter spares the check on the precondition, so if you want to take the responsibility yourself, you can. This can be used under circumstances where using exceptions are not permitted or when fixing a performance bottleneck.



    Example 1: std::vector element access:



    std::vector<int> vec;
    vec.at(n) // throws std::out_of_range
    vec[n] // potentially UB, thus your own responsibility


    Example 2: std::optional access:



    std::optional<int> optn;
    optn.value() // throws std::bad_optional_access
    *optn // potentially UB, thus your own responsibility


    Now on to std::variant. Directly accessing an alternative somewhat follows this pattern:



    std::variant<std::string, int> var;
    std::get<int>(var) // potentially throwing std::bad_variant_access
    *std::get_if<int>(&var) // potentially UB, thus your own responsibility


    But this time the signature changes, we have to inject * and &. The downside of this is that we don't get automatic move semantics. One more thing to keep in your mind...



    But it gets worse if you have a look at std::visit(Visitor&& vis, Variants&&... vars). There is no noexcept alternative for it, although it only throws




    if any variant in vars is valueless_by_exception.




    This means for visiting variants you cannot choose to take the responsibility yourself, and if you have no choice and must avoid exceptions, you cannot visit std::variants at all with standard tooling! (apart from the terrible workaround of switching on variant::index())



    To me, this looks like a pretty bad design oversight... or there a reason for this? And in case I'm right about the oversight, is there an initiative to fix this in the standard?










    share|improve this question

























      3












      3








      3







      For some standard library classes, access to parts of their contents may legitimately fail. Usually you have the choice between some potentially throwing method an one that is marked noexcept. The latter spares the check on the precondition, so if you want to take the responsibility yourself, you can. This can be used under circumstances where using exceptions are not permitted or when fixing a performance bottleneck.



      Example 1: std::vector element access:



      std::vector<int> vec;
      vec.at(n) // throws std::out_of_range
      vec[n] // potentially UB, thus your own responsibility


      Example 2: std::optional access:



      std::optional<int> optn;
      optn.value() // throws std::bad_optional_access
      *optn // potentially UB, thus your own responsibility


      Now on to std::variant. Directly accessing an alternative somewhat follows this pattern:



      std::variant<std::string, int> var;
      std::get<int>(var) // potentially throwing std::bad_variant_access
      *std::get_if<int>(&var) // potentially UB, thus your own responsibility


      But this time the signature changes, we have to inject * and &. The downside of this is that we don't get automatic move semantics. One more thing to keep in your mind...



      But it gets worse if you have a look at std::visit(Visitor&& vis, Variants&&... vars). There is no noexcept alternative for it, although it only throws




      if any variant in vars is valueless_by_exception.




      This means for visiting variants you cannot choose to take the responsibility yourself, and if you have no choice and must avoid exceptions, you cannot visit std::variants at all with standard tooling! (apart from the terrible workaround of switching on variant::index())



      To me, this looks like a pretty bad design oversight... or there a reason for this? And in case I'm right about the oversight, is there an initiative to fix this in the standard?










      share|improve this question













      For some standard library classes, access to parts of their contents may legitimately fail. Usually you have the choice between some potentially throwing method an one that is marked noexcept. The latter spares the check on the precondition, so if you want to take the responsibility yourself, you can. This can be used under circumstances where using exceptions are not permitted or when fixing a performance bottleneck.



      Example 1: std::vector element access:



      std::vector<int> vec;
      vec.at(n) // throws std::out_of_range
      vec[n] // potentially UB, thus your own responsibility


      Example 2: std::optional access:



      std::optional<int> optn;
      optn.value() // throws std::bad_optional_access
      *optn // potentially UB, thus your own responsibility


      Now on to std::variant. Directly accessing an alternative somewhat follows this pattern:



      std::variant<std::string, int> var;
      std::get<int>(var) // potentially throwing std::bad_variant_access
      *std::get_if<int>(&var) // potentially UB, thus your own responsibility


      But this time the signature changes, we have to inject * and &. The downside of this is that we don't get automatic move semantics. One more thing to keep in your mind...



      But it gets worse if you have a look at std::visit(Visitor&& vis, Variants&&... vars). There is no noexcept alternative for it, although it only throws




      if any variant in vars is valueless_by_exception.




      This means for visiting variants you cannot choose to take the responsibility yourself, and if you have no choice and must avoid exceptions, you cannot visit std::variants at all with standard tooling! (apart from the terrible workaround of switching on variant::index())



      To me, this looks like a pretty bad design oversight... or there a reason for this? And in case I'm right about the oversight, is there an initiative to fix this in the standard?







      c++ c++17 variant noexcept






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Dec 27 at 14:32









      Tobi

      883220




      883220
























          1 Answer
          1






          active

          oldest

          votes


















          1















          This means for visiting variants you cannot choose to take the responsibility yourself




          Sure you can. The "valueless-by-exception" state can only happen if you assign or emplace a value into an existing variant. Furthermore, by definition, it can only happen if an exception is actually thrown during these processes. That is not a state that ever just happens to a random variant.



          If you take responsibility to ensure that you either never emplace/assign to a variant, or that the types you use never throw in those circumstances, or that you respond to any exceptions from doing so in such a way that the variant that provoked it is not being talked to (ie: if bad_alloc is thrown, your application doesn't catch it; it just shuts down), then you don't have to care about this possibility.



          Basically, if you're already coding to avoid exceptions, the non-noexcept status of visit is irrelevant. No variant will ever get into the "valueless-by-exception" unless an exception is thrown.






          share|improve this answer





















          • No: if exceptions are disabled, std::visit does not exist in the standard library.
            – Tobi
            Dec 27 at 14:44










          • @Tobi: I don't know of any compiler that actively removes non-noexcept functions when you disable exception handling. My general understanding is that turning off exception handling either removes throw statements or causes them to terminate the application.
            – Nicol Bolas
            Dec 27 at 14:44












          • For example, Apple Clang doesn't let you throw std::bad_variant_access if you target macOS 10.13 and earlier (it's an issue of the C++ runtime, see here). Thus std::visit does not exist in that case.
            – Tobi
            Dec 27 at 14:49










          • @Tobi: But that's not an issue of disabling exceptions; it's an issue of a incomplete C++17 runtime. Basically, I'm saying that it's the fault of how iOS/MacOS handles its C++ runtime, not the fault of the standard.
            – Nicol Bolas
            Dec 27 at 14:52












          • It's just one example. You might want to spare the extra runtime check and the generated exception-throwing code for any reason. In all the other examples the choice is yours, but not for std::visit.
            – Tobi
            Dec 27 at 14:56











          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',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          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
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53946674%2fnoexcept-visitation-for-stdvariant%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          1















          This means for visiting variants you cannot choose to take the responsibility yourself




          Sure you can. The "valueless-by-exception" state can only happen if you assign or emplace a value into an existing variant. Furthermore, by definition, it can only happen if an exception is actually thrown during these processes. That is not a state that ever just happens to a random variant.



          If you take responsibility to ensure that you either never emplace/assign to a variant, or that the types you use never throw in those circumstances, or that you respond to any exceptions from doing so in such a way that the variant that provoked it is not being talked to (ie: if bad_alloc is thrown, your application doesn't catch it; it just shuts down), then you don't have to care about this possibility.



          Basically, if you're already coding to avoid exceptions, the non-noexcept status of visit is irrelevant. No variant will ever get into the "valueless-by-exception" unless an exception is thrown.






          share|improve this answer





















          • No: if exceptions are disabled, std::visit does not exist in the standard library.
            – Tobi
            Dec 27 at 14:44










          • @Tobi: I don't know of any compiler that actively removes non-noexcept functions when you disable exception handling. My general understanding is that turning off exception handling either removes throw statements or causes them to terminate the application.
            – Nicol Bolas
            Dec 27 at 14:44












          • For example, Apple Clang doesn't let you throw std::bad_variant_access if you target macOS 10.13 and earlier (it's an issue of the C++ runtime, see here). Thus std::visit does not exist in that case.
            – Tobi
            Dec 27 at 14:49










          • @Tobi: But that's not an issue of disabling exceptions; it's an issue of a incomplete C++17 runtime. Basically, I'm saying that it's the fault of how iOS/MacOS handles its C++ runtime, not the fault of the standard.
            – Nicol Bolas
            Dec 27 at 14:52












          • It's just one example. You might want to spare the extra runtime check and the generated exception-throwing code for any reason. In all the other examples the choice is yours, but not for std::visit.
            – Tobi
            Dec 27 at 14:56
















          1















          This means for visiting variants you cannot choose to take the responsibility yourself




          Sure you can. The "valueless-by-exception" state can only happen if you assign or emplace a value into an existing variant. Furthermore, by definition, it can only happen if an exception is actually thrown during these processes. That is not a state that ever just happens to a random variant.



          If you take responsibility to ensure that you either never emplace/assign to a variant, or that the types you use never throw in those circumstances, or that you respond to any exceptions from doing so in such a way that the variant that provoked it is not being talked to (ie: if bad_alloc is thrown, your application doesn't catch it; it just shuts down), then you don't have to care about this possibility.



          Basically, if you're already coding to avoid exceptions, the non-noexcept status of visit is irrelevant. No variant will ever get into the "valueless-by-exception" unless an exception is thrown.






          share|improve this answer





















          • No: if exceptions are disabled, std::visit does not exist in the standard library.
            – Tobi
            Dec 27 at 14:44










          • @Tobi: I don't know of any compiler that actively removes non-noexcept functions when you disable exception handling. My general understanding is that turning off exception handling either removes throw statements or causes them to terminate the application.
            – Nicol Bolas
            Dec 27 at 14:44












          • For example, Apple Clang doesn't let you throw std::bad_variant_access if you target macOS 10.13 and earlier (it's an issue of the C++ runtime, see here). Thus std::visit does not exist in that case.
            – Tobi
            Dec 27 at 14:49










          • @Tobi: But that's not an issue of disabling exceptions; it's an issue of a incomplete C++17 runtime. Basically, I'm saying that it's the fault of how iOS/MacOS handles its C++ runtime, not the fault of the standard.
            – Nicol Bolas
            Dec 27 at 14:52












          • It's just one example. You might want to spare the extra runtime check and the generated exception-throwing code for any reason. In all the other examples the choice is yours, but not for std::visit.
            – Tobi
            Dec 27 at 14:56














          1












          1








          1







          This means for visiting variants you cannot choose to take the responsibility yourself




          Sure you can. The "valueless-by-exception" state can only happen if you assign or emplace a value into an existing variant. Furthermore, by definition, it can only happen if an exception is actually thrown during these processes. That is not a state that ever just happens to a random variant.



          If you take responsibility to ensure that you either never emplace/assign to a variant, or that the types you use never throw in those circumstances, or that you respond to any exceptions from doing so in such a way that the variant that provoked it is not being talked to (ie: if bad_alloc is thrown, your application doesn't catch it; it just shuts down), then you don't have to care about this possibility.



          Basically, if you're already coding to avoid exceptions, the non-noexcept status of visit is irrelevant. No variant will ever get into the "valueless-by-exception" unless an exception is thrown.






          share|improve this answer













          This means for visiting variants you cannot choose to take the responsibility yourself




          Sure you can. The "valueless-by-exception" state can only happen if you assign or emplace a value into an existing variant. Furthermore, by definition, it can only happen if an exception is actually thrown during these processes. That is not a state that ever just happens to a random variant.



          If you take responsibility to ensure that you either never emplace/assign to a variant, or that the types you use never throw in those circumstances, or that you respond to any exceptions from doing so in such a way that the variant that provoked it is not being talked to (ie: if bad_alloc is thrown, your application doesn't catch it; it just shuts down), then you don't have to care about this possibility.



          Basically, if you're already coding to avoid exceptions, the non-noexcept status of visit is irrelevant. No variant will ever get into the "valueless-by-exception" unless an exception is thrown.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Dec 27 at 14:42









          Nicol Bolas

          282k33466641




          282k33466641












          • No: if exceptions are disabled, std::visit does not exist in the standard library.
            – Tobi
            Dec 27 at 14:44










          • @Tobi: I don't know of any compiler that actively removes non-noexcept functions when you disable exception handling. My general understanding is that turning off exception handling either removes throw statements or causes them to terminate the application.
            – Nicol Bolas
            Dec 27 at 14:44












          • For example, Apple Clang doesn't let you throw std::bad_variant_access if you target macOS 10.13 and earlier (it's an issue of the C++ runtime, see here). Thus std::visit does not exist in that case.
            – Tobi
            Dec 27 at 14:49










          • @Tobi: But that's not an issue of disabling exceptions; it's an issue of a incomplete C++17 runtime. Basically, I'm saying that it's the fault of how iOS/MacOS handles its C++ runtime, not the fault of the standard.
            – Nicol Bolas
            Dec 27 at 14:52












          • It's just one example. You might want to spare the extra runtime check and the generated exception-throwing code for any reason. In all the other examples the choice is yours, but not for std::visit.
            – Tobi
            Dec 27 at 14:56


















          • No: if exceptions are disabled, std::visit does not exist in the standard library.
            – Tobi
            Dec 27 at 14:44










          • @Tobi: I don't know of any compiler that actively removes non-noexcept functions when you disable exception handling. My general understanding is that turning off exception handling either removes throw statements or causes them to terminate the application.
            – Nicol Bolas
            Dec 27 at 14:44












          • For example, Apple Clang doesn't let you throw std::bad_variant_access if you target macOS 10.13 and earlier (it's an issue of the C++ runtime, see here). Thus std::visit does not exist in that case.
            – Tobi
            Dec 27 at 14:49










          • @Tobi: But that's not an issue of disabling exceptions; it's an issue of a incomplete C++17 runtime. Basically, I'm saying that it's the fault of how iOS/MacOS handles its C++ runtime, not the fault of the standard.
            – Nicol Bolas
            Dec 27 at 14:52












          • It's just one example. You might want to spare the extra runtime check and the generated exception-throwing code for any reason. In all the other examples the choice is yours, but not for std::visit.
            – Tobi
            Dec 27 at 14:56
















          No: if exceptions are disabled, std::visit does not exist in the standard library.
          – Tobi
          Dec 27 at 14:44




          No: if exceptions are disabled, std::visit does not exist in the standard library.
          – Tobi
          Dec 27 at 14:44












          @Tobi: I don't know of any compiler that actively removes non-noexcept functions when you disable exception handling. My general understanding is that turning off exception handling either removes throw statements or causes them to terminate the application.
          – Nicol Bolas
          Dec 27 at 14:44






          @Tobi: I don't know of any compiler that actively removes non-noexcept functions when you disable exception handling. My general understanding is that turning off exception handling either removes throw statements or causes them to terminate the application.
          – Nicol Bolas
          Dec 27 at 14:44














          For example, Apple Clang doesn't let you throw std::bad_variant_access if you target macOS 10.13 and earlier (it's an issue of the C++ runtime, see here). Thus std::visit does not exist in that case.
          – Tobi
          Dec 27 at 14:49




          For example, Apple Clang doesn't let you throw std::bad_variant_access if you target macOS 10.13 and earlier (it's an issue of the C++ runtime, see here). Thus std::visit does not exist in that case.
          – Tobi
          Dec 27 at 14:49












          @Tobi: But that's not an issue of disabling exceptions; it's an issue of a incomplete C++17 runtime. Basically, I'm saying that it's the fault of how iOS/MacOS handles its C++ runtime, not the fault of the standard.
          – Nicol Bolas
          Dec 27 at 14:52






          @Tobi: But that's not an issue of disabling exceptions; it's an issue of a incomplete C++17 runtime. Basically, I'm saying that it's the fault of how iOS/MacOS handles its C++ runtime, not the fault of the standard.
          – Nicol Bolas
          Dec 27 at 14:52














          It's just one example. You might want to spare the extra runtime check and the generated exception-throwing code for any reason. In all the other examples the choice is yours, but not for std::visit.
          – Tobi
          Dec 27 at 14:56




          It's just one example. You might want to spare the extra runtime check and the generated exception-throwing code for any reason. In all the other examples the choice is yours, but not for std::visit.
          – Tobi
          Dec 27 at 14:56


















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


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


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





          Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


          Please pay close attention to the following guidance:


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


          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%2fstackoverflow.com%2fquestions%2f53946674%2fnoexcept-visitation-for-stdvariant%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

          Monofisismo

          Angular Downloading a file using contenturl with Basic Authentication

          Olmecas