Wednesday 16 January 2013

std::current_exception()

Ok, this is a very nice idea, and also very simple. std::current_exception returns a std::exception_ptr to the exception currently being handled by a catch{} block. The following snippet shows it in action quite well, but I don't expect that this kind of thing will take off for current_exception. It might even be something of an antipattern in its current form:
 try  
 {  
  someFunction();  
 }  
 catch(...)  
 {  
  auto exPtr = std::current_exception();  
  /* now we have an exception pointer to the current exception... */  
 }  

This is all well and good, but what's the point? In search of that we look at bit deeper at std::exception_ptr, which provides shared ownership semantics for exceptions in a similar fashion to shared ownership of objects provided by std::shared_ptr. Exception pointers can be created from exceptions:
 try  
 {  
  someFunction()  
 }  
 catch(std::exception &ex)  
 {  
  std::exception_ptr exPtr = std::make_exception_ptr(ex);  
  /* now we have an exception ptr... */
 }  

The C++11 standard says that make_exception_ptr works roughly like this:
 template<class E> exception_ptr make_exception_ptr(E e) noexcept  
 {  
  try   
  {  
   throw e;  
  }   
  catch(...)  
  {  
   return current_exception();  
  }  
 }  

It can't be the case that std::current_exception exists only to service std::make_exception_ptr, so what's all this about? The answer shouldn't surprise you: threading. Exceptions are notoriously bad at cross-thread error propagation and until C++11 there's been no simple cross-platform way of doing this. Sure, you could catch your exception, stash it somewhere and let another thread rethrow it to code that can do something about it, but the problem is that you need to manually account for all types of exception that can be thrown. This doesn't scale well and leaves you responsible for actively managing the lifetime of your exception object.

Using
std::current_exception() to get a  std::exception_ptr to anything that's been thrown (and remember, you can throw just about anything in C++!), you can store a container of those exception pointers in one thread and use std::rethrow_exception to propagate them again in another thread. This is possible because, although the precise definition of std::exception_ptr is unspecified, it is untemplated and therefore opaque enough to store in a homogeneous container. As soon as your exception is no longer referenced by at least one std::exception_ptr, its lifetime ends and the resources are freed up. 

What could be simpler?

The "transporting exception across the thread boundary" pattern is implemented in this example from Microsoft.

Monday 14 January 2013

std::to_string()

Starting simple, I was really pleased and a little surprised to see to_string (and its sibling, to_wstring) pop up. It's a feature that we've really needed for more time than I care to consider and it removes the need for the fairly foul: 

 char buff[12] = {0};  
 sprintf(buff, "%d", INT_MIN);  
 /* convert to std::string if we like */  

or the moderately foul:


 std::ostringstream mystream;  
 mystream << INT_MIN;  
 std::string s = mystream.str();  

I'm not saying there aren't proper uses for sprintf or stringstream, it's just that the above seems such a waste of time when you consider Python's str() or even C#'s versatile Convert.ToString(). Neither of my examples are very expressive and the first gets even worse if you're developing for a Microsoft platform and you have to start considering sprintf_s and the like.

std::to_string is long overdue and extremely simple to use:


 float f = 3.14;  
 std::string piString = std::to_string(f);  

What could be easier than that? No worrying about buffer sizes, no baroque format string incantations, no stringstream wastes. That ends the first real post. If anyone posts comments, I promise to read them. Is anybody out there?

Hi!

I'm a big fan of the new(ish) C++11 standard. It's not that I think it patches the problems with previous C++ standards: it's still more than possible to leak memory, construct truly horrible deadlock scenarios and accidentally take a copy of vast amounts of data. The difference is that it enables and encourages a way of writing C++ code that dramatically reduces the likelihood of you encountering the above situations. Please don't believe me, there's lots written on this subject by people far more intelligent than me and I hope you have the time to check it out.

I was inspired to have a go at writing this technical blog by the sheer number of surprising things that crop up when I'm watching the experts discuss the new headline C++11 features. I'm talking mostly about the types added to the standard library, some of which are incredibly feature rich and expressive and have received almost no coverage online. Also, there is a distinct paucity of examples that I might be able to begin to address here.

So that's it. I'm going to give it a go. At some point, sooner or later, I will run out of things that surprise me in C++11 and then I'll just stop. Until then, I hope these posts are of at least some small utility to some of you.