c++c++17rvonrvo

can't find a way to make garanteed return value optimization work


Why the clang says call to deleted constructor of 'Block<Tuple>::Self' (aka 'Block<Tuple>') in the call of Block<Tuple>::a1() when I delete the move constructor?

c++17 clang version 9.0.0 (tags/RELEASE_900/final) Target: x86_64-pc-linux-gnu Thread model: posix InstalledDir: /usr/bin

template<typename tRecord>
struct Block {

    using Self = Block<tRecord>;

    Size mUsedBytes;
    bool mModified;

    union Data {
        char mBytes[4_KB];
        tRecord mRecord;
    };
    Data mData;

    Block() {
        mardCpp::Log::info("constructing");
    };

    Block(const Block &block) = delete;
    Block(Block &&block) = delete;

    static Self a1() {
        Self block;
        return block;
    }

    static Self a2() {
        return Self();
    }
};

From what I've readed, I could have garanteed rvo if I deleted the copy and move constructors. The compiler would complain in situations where he could not do rvo and the code would not compile. For instance, when I delete the copy constructor and define the move one with just throwing an error, he actually optimizes the calling of a1, since I got no errors. But when I delete the move constructor, the code does not even compile.


Solution

  • This code:

    static Self a1() {
        Self block;
        return block;
    }
    

    is not part of the so-called "guaranteed copy elision". It still has the same behaviour as in older versions of C++, i.e. it is a copy elision context but the copy/move construction must be valid and the compiler doesn't have to perform the elision.

    The a2 code is "guaranteed" as such and you should not get errors from that.