cplusplus.co.il

Exceptional initialization list

Posted on: 30/11/2010

Using the initialization list is very much encouraged in C++, and rightfully so – it has many benefits. But what happens if one of your members fails at initialization and actually throws an exception? Even worse: what happens if that member’s constructor throws an exception not in your exception specification list?

That’s what happened to me just the other day; I was using SWIG to wrap a C++ class to Python (by the way, SWIG is just plain awesome), and since exception specification causes wrapping of the exception classes as well, it’s a good idea to use that. So there I was, declaring my constructor to only throw instances of std::runtime_error.. Only to discover that one of my members (implemented elsewhere) could actually throw a const char*.

Luckily, I was familiar with the idea of catching exceptions raised within the initialization list, and that’s exactly what was needed to save the day. The required syntax is hereby presented:

struct myclass {
    myclass () throw(std::runtime_error)
        try
        : m_member("test") {
            // normal constructor code
        }
        catch (const char *err) {
            throw std::runtime_error(err);
        }

    private:
        someotherclass m_member;
};

There are ofcouse some limitations on what you can do within the catch-block, the major one being that you must throw something; You cannot continue normal execution having failed initializing the object — if nothing is thrown when reaching the end of the catch-block, the caught exception is automatically rethrown.

Extra details and more in-depth discussion of the mechanism can be found at GotW#66.

Advertisements

9 Responses to "Exceptional initialization list"

Why would you enumerate an exception specification list? It’s a fundamentally broken “feature”.

One note only, exception specifications are deprecated in upcoming C++ standard and for good reason. In current standard they are seen as a bad practice so you shouldn’t use them at all.

The try-catch constructor is very handy though but VC provides a very neat extension allowing you to not throw exception.

struct my
{
 my()
 try : m_member("A")
 {
 }
 catch (exception const&)
 {
   return; // MS Extension, object is created without exception 
 }
}

Some points to mention:
You should not use throw specification as it is declared as deprecated in C++0x and it doesn’t work as expected.

And the last one, never throw types not derived from std::exception or your BaseException class 🙂

@NN: Are you VC really behaves like that? Allowing a not-fully constructed object to live on?! Sounds very evil.

Hopefully it’s the old v6 and not the never ones.

@NN

So what does that MS extension mean? That I’ll get a new object that potentially isn’t initialized?
Can you give an example of where this is useful?

Yes, that’s right.
You can have object which is not fully initialized:

#include <exception>
#include <iostream>
#include <string>

bool throwException() { throw std::exception(); return true; }

class standardStyle
{
public:
	standardStyle()
		try : b_(throwException())
	{
		s = "No Exception";
	}
	catch (std::exception const&)
	{		
	}

	bool b_;
	std::string s;
};

class vcExtension
{
public:
	vcExtension()
		try : s(), b(throwException()), i(1)
		{
			s = "1";
		}
		catch (std::exception const&)
		{
			s = "Caught Exception!";
			return;
		}

	std::string s;
	bool b;
	int i;
};


int main()
{
	try
	{
		standardStyle st;
	}
	catch (std::exception const&)
	{
		// Object was not created...
	}

	// Object is created but only members before throw are initialized!
	vcExtension vc;
	
	std::cout << vc.s << "\n"; // Great !
	std::cout << vc.i << "\n"; // Not so good
	
	return 0;
}

Where it is useful ? It is useful, but not in that way of course 😉

It is useful if you want to continue execution even if member constructor fails.
So for this you should use boost::optional which solves the problem:

class X
{
 boost::optional<ThrowMemberConstructor> t;

public:
 X() 
 {
  try
  {
   // Delayed construction
   v = boost::in_place(arg1, arg2);
  }
  catch(std::exception const&)
  {
  }
 }
}

Question: what plugin are you using to display code snippets? It looks really nice 🙂

Thanks 🙂

That’s called “SyntaxHighlighter”, and you can get its details by pressing the rightmost question-mark button that pops at the top of the sourcecode section when you hover your mouse over it.
I believe all blogs under wordpress.com have it by default (also within comments), and you can use it by writing the following:

Xsourcecode language=”cpp”]
// some code
X/sourcecode]

Where ‘X’ should be replaced with a ‘[‘.

This is one of those things that prove that C++ can’t be learned. And by the way aren’t exception specifiers deprecated in C++0x?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: