Search code examples
c++scopec++17constexprif-constexpr

Extend object lifetime/scope from a `if constexpr` branch


Say we have the following code

struct MyClass
{
    MyClass() = delete;  // or MyClass() { }
    MyClass(int) { }
    void func() { }
};

int main()
{
    if constexpr (std::is_default_constructible_v<MyClass>) {
        MyClass myObj;
    } else {
        MyClass myObj(10);
    }

    myObj.func();  // Error
}

Here I am using if constexpr to determine whether the class is default-constructible (or not), and then create an object accordingly. In a way, I naively thought this would simplify the different branches down to just the one that's true, i.e.

    if constexpr (true) {
        /* instruction branch 1 */
    } else if constexpr (false) {
        /* instruction branch 2 */
    }

simply becomes

    /* instruction branch 1 */

But in reality, it is probably more like this

    {
        /* instruction branch 1 */
    }

But then the question becomes (going to back to the the very first example), how can I can I keep myObj in scope outside the { ... }?


Solution

  • First, your code won't work. if constexpr really needs its condition to be dependent.

    I'll fix it.

    template<class MyClass>
    void func() {
      MyClass myObj = []{
        if constexpr (std::is_default_constructible_v<MyClass>) {
          return MyClass{};
        } else {
          return MyClass(10);
        }
      }();
      myObj.func();
    }
    

    now

    int main() {
      func<MyClass>();
    }
    

    solves your problem.

    Note that under rules, no copies or moves of MyClass occur in the above code.