9.3. Making an Initializer List Exception-Safe

Problem

You have to initialize your data members in the constructor’s initializer list, and, therefore, cannot use the approach described in Recipe 9.2.

Solution

Use a special syntax for try and catch that catches exceptions thrown in the initializer list. Example 9-3 shows how.

Example 9-3. Handling exceptions in an initializer

#include <iostream>
#include <stdexcept>

using namespace std;

// Some device
class Device {
public:
   Device(int devno) {
      if (devno == 2)
         throw runtime_error("Big problem");
   }
  ~Device() {}
private:
   Device();
};

class Broker {
  
public:
   Broker (int devno1, int devno2)
      try : dev1_(Device(devno1)),   // Create these in the initializer
            dev2_(Device(devno2)) {} // list.
      catch (...) {
         throw; // Log the message or translate the error here (see
                // the discussion)
      }
  ~Broker() {}

private:
   Broker();
   Device dev1_;
   Device dev2_;
};

int main() {

   try {
      Broker b(1, 2);
   }
   catch(exception& e) {
      cerr << "Exception: " << e.what() << endl;
   }
}

Discussion

The syntax for handling exceptions in initializers looks a little different from the traditional C++ syntax because it uses the try block as the constructor body. The critical part of Example 9-3 is the Broker constructor:

Broker (int devno1, int devno2) // Constructor header is the same try : // Same idea as a try {...} block dev1_(Device(devno1)), // The initializers follow dev2_(Device(devno2)) { // This is the constructor body. } catch (...) { // The catch handler is *after* throw; // the ...

Get C++ Cookbook now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.