Search code examples
c++exceptionconstructorexception-safety

Throwing exception in constructor before member initializer list?


As an example, say I have the class

class A{
    B& foo;
};

and I want to initialize this class with a constructor that takes in a vector and an index (just for example).

So I get

    explicit A(std::vector<B>& lst, int index):
        foo(lst[index])
    {};

However, accessing a random index in the vector is unsafe, since it would be UB if it was out of bounds. So, I throw an exception

    explicit A(std::vector<B>& lst, int index):
        foo(lst[index])
    {
        if (index >= lst.size()){
            //throw blah blah
        }
    };

However, this doesn't actually save me at all, because the member initializer list is ran before the constructor body. So the possible out of bounds access would happen first, and only after that the check runs.

My current thoughts to solve this are:

  1. Assign values in the constructor body.

    • everything is default constructed first, repeats work
    • I know it's not good practice to store references as class members, but this also means that in general we can't throw on any non-default constructable values class members
      • though I guess it would technically make sense to never be able to throw on a non-default constructable object for exception safety
  2. Make this check happen before calling the constructor

    • Hard to enforce

Are there any language abilities that let me throw an exception early? And if not, what is standard practice for this situation.


Solution

  • Besides the solutions in the comments, you can use the ternary operator:

    explicit A(std::vector<B>& lst, int index):
        foo(lst[index < lst.size() ? index : throw blah_blah()])
    {}
    

    It requires no helper functions and allows customizing your throw.