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)   
|