c++c++17rvo

constexpr if and the return value optimization


I have this code:

#include <string>

class A {
 public:
//    A(A const &) = delete;   // Code fails if this is uncommented.
    explicit A(int);
    explicit A(::std::string const &);

 private:
    ::std::string myname_;
    int foo_;
};

static constexpr bool which = false;

A test(::std::string const &s, int a)
{
    if constexpr (which) {
        A x{a};
        return x;
    } else {
        A y{s};
        return y;
    }
}

This code fails if A has a deleted copy constructor. But, given the rules about return type for functions with if constexpr in them, it seems like the compiler should be applying RVO here.

Is there a reason why it isn't, other than it being an overlooked case in the language specification?


Solution

  • This has nothing to do with if constexpr

    Simply this code is not allowed to compile:

    class A {
     public:
        A(A const &) = delete;
        explicit A(int);
    };
    
    A test(int a)
    {
        A x{a};
        return x; // <-- error call to a deleted constructor `A(A const &) = delete;`
    }
    

    The changes in C++17 you are thinking of have to do with temporary materialization and don't apply to NRVO because x is not a prvalue.

    For instance this code was illegal pre C++17 and now it is allowed:

    A test(int a)
    {
        return A{a}; // legal since C++17
    }