Search code examples
c++default-constructorvariable-declaration

Declare variable, whose type has an deleted default constructor, without a value


I want to initialize a variable in multiple if-else branches, to use it later, basically like this:

Foo foo;

if (someCondition) {
    std::string someString = getTheString();
    // do some stuff
    foo = Foo(someString);
} else {
    int someInt = getTheInt();
    //do some other stuff maybe
    foo = Foo(someInt);
}

// use foo here

Unfortunately in this example the type Foo has a deleted default constructor, so the code above doesn't compile. Is there a way to initialize such a variable in this manner?

EDIT:

As you can see in my Example, I'm using different constructors and also do other things in the if/else blocks, so unfortunately the ternary operator doesn't work.
If there is no way, without foo being a pointer, I could obviously take a different approach, but I was curious, if my approach somehow worked.


Solution

  • You haven't told us why you can't use a pointer ... but, in the meantime, here's is a solution that ostensibly is pointer-free:

    #include <optional>    
    std::optional<Foo> foo;
    
    if (someCondition) {
        std::string someString = getTheString();
        // do some stuff
        foo.emplace(someString);
    } else {
        int someInt = getTheInt();
        //do some other stuff maybe
        foo.emplace(someInt);
    }
    if (foo.has_value()) { /* use foo here */ }
    

    If you have a coding standard or something that prohibits the use of raw pointers (and new), then you can use std::unique_ptr.

    #include <memory>
    std::unique_ptr<Foo> foo;
    
    if (someCondition) {
        std::string someString = getTheString();
        // do some stuff
        foo = std::make_unique<Foo>(someString);
    } else {
        int someInt = getTheInt();
        //do some other stuff maybe
        foo = std::make_unique<Foo>(someInt);
    }
    if (foo) {/* use foo here */}
    

    You could also put your Foo-creation logic in a separate function (or lambda):

    auto getFoo(/* ... */) {
        if (someCondition) {
            std::string someString = getTheString();
            // do some stuff
            return Foo(someString);
        } else {
            int someInt = getTheInt();
            //do some other stuff maybe
            return Foo(someInt);
       }
    }
    // ...
    Foo foo = getFoo(/*...*/);
    // use foo here