home bbs files messages ]

Forums before death by AOL, social media and spammers... "We can't have nice things"

   comp.lang.c++.moderated      Moderated discussion of C++ superhackery      33,346 messages   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]

   Message 31,951 of 33,346   
   Marc to Dmitry Potapov   
   Re: Forcing non-throwing arguments   
   22 Feb 12 08:09:47   
   
   87fa85df   
   From: marc.glisse@gmail.com   
      
   Dmitry Potapov  wrote:   
      
   > There was a big problem in C++03, when accepting template argument, you   
   > know nothing about exceptions which can occur while you're using this   
   > argument. Sometimes, this can lead to additional logic and performance   
   > penalty.   
   >   
   > As for me, I don't care about exceptions type, it is the caller who   
   > should handle them. My job is to prevent resource leaks and I need to   
   > know if execution sequence can be interrupted by exception.   
   >   
   > In C++11 there is noexcept operator, which allows to determine if some   
   > expression can throw an exception. From this, it is become possible to   
   > provide two function implementations, one for exception throwing   
   > argument, and second one with noexcept exception specification.   
      
   Yes, that's part of the goal. std::vector is one typical user.   
      
   > For example, consider class C with template c'tor which allocates some   
   > resources and then calls member function f() of the argument. It is a   
   > good practice to wrap resources with unique_ptr or something similar in   
   > order to avoid resource leak, but this introduces slight overhead for   
   > non-throwing arguments, which can be unacceptable in   
   > performance-critical applications.   
      
   Does it? In most cases it makes no difference at all.   
      
   > #include    
   > #include    
   >   
   > struct A {   
   >      void f() {}   
   > };   
   >   
   > struct B {   
   >      void f() noexcept {}   
   > };   
   >   
   > class C {   
   >      template    
   >      C(T t, std::true_type) noexcept   
   >      {   
   >          t.f();   
   >          std::cout << "here we can use straight and simple logic here as   
   no"   
   >              " exceptions are possible"<< std::endl;   
   >      }   
   >   
   >      template    
   >      C(T t, std::false_type)   
   >      try   
   >      {   
   >          // resources allocation here   
   >          // ...   
   >          t.f();   
   >          std::cout << "here we should use a bit more complicated logic   
   > to avoid"   
   >              " resource and memory leaks" << std::endl;   
   >      }   
   >      catch (...)   
   >      {   
   >          std::cerr << "here we must free resources acquired" << std::endl;   
   >      }   
   >   
   > public:   
   >      template    
   >      C(T t) noexcept(noexcept(t.f()))   
   >          : C(t, std::integral_constant())   
   >      {   
   >      }   
   > };   
   >   
   > int main()   
   > {   
   >      A a;   
   >      B b;   
   >      C c(a);   
   >      C c2(b);   
   > }   
      
   Except for the fact that iostreams may throw, a good compiler can transform:   
   try { call_nothrow_function(); } catch...   
   into just:   
   call_nothrow_function();   
      
   > In the example above, we can delete c'tor overloading with false_type in   
   > order to forbid throwing arguments.   
      
   Yes, although I think I'd rather use sfinae to remove the constructor:   
      
    template ().f())>::type>   
    C(T t) noexcept;   
      
   > Fly in the ointment:   
   > Thoughts about such trick came to me when I worked on class which   
   > accepts functor, which can be just a std::plus. Unfortunately helper   
   > functors declared as:   
   >   
   > T operator()(const T& x, const T& y) const;   
   >   
   > Not as:   
   >   
   > T operator()(const T& x, const T& y) const noexcept(x+y);   
      
   you want noexcept(noexcept(x+y)) here.   
      
   > So, this reduces the area where this trick is applicable.   
      
   Yes, the C++11 standard was quite conservative in marking things   
   constexpr and/or noexcept. Your library vendor is allowed to add those   
   noexcept, but you won't be able to rely on it.   
      
      
   --   
         [ See http://www.gotw.ca/resources/clcm.htm for info about ]   
         [ comp.lang.c++.moderated.    First time posters: Do this! ]   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]


(c) 1994,  bbs@darkrealms.ca