Dean
Dean

Reputation: 6960

Avoiding destructor call for a specific exception

I'm simplifying my problem here since I have a pretty large codebase and I can't make a mcve.

I have an object which might or might not be constructed successfully. If not, an exception of kind ObjectUnsupported is thrown in its constructor

class Object {
public:
  Object() {

    read_data1();
    ..
    if(unsupported_kind == true)
      throw ObjectUnsupported();
    ..
    read_data2();
  }
  std::vector<char> data1;
  std::vector<char> data2;
};

data1 is always read while data2 is only available for supported objects.

Now, I'm trying to construct an object somewhere else by using a smart pointer

std::unique_ptr<Object> obj;
try {
  obj = std::make_unique<Object>();
} catch(ObjectUnsupported& ex) {
  object_is_unsupported = true;
}

if(object_is_unsupported) {
  if(checkIfDataIsNeeded(obj->data1) == false)
    return; // We didn't need it anyway
  else
    throw RuntimeError(); // Data was needed! Abort!
}

data1 is always read while data2 is not but the point here is: I might need that data2 or I might not need the object at all.

The code above doesn't work since the destructor for the obj smart pointer is called therefore rendering my subsequent code wrong.

How can I achieve my goal?

Upvotes: 2

Views: 68

Answers (1)

Richard Hodges
Richard Hodges

Reputation: 69882

Throwing an exception from a constructor does not leave you with a half-constructed object. By design, that object does not exist. All the members that were constructed up till the point of the exception will be destroyed.

The solution here is for your object to support a flag that indicates how much data it has.

for example:

class Object {
public:
    Object() {

        read_data1();
        ..
        if(!unsupported_kind)
        {
            read_data2();
            _has_supported_data = true;
        }
    }

    bool has_supported_data() const {
        return _has_supported_data;
    }

    std::vector<char> data1;
    std::vector<char> data2;

private:
    bool _has_supported_data = false;
};

Upvotes: 2

Related Questions