C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Custom call convention per type

From: Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>
Date: Mon, 8 Aug 2022 11:59:41 +0100
On Thu, Jul 28, 2022 at 10:26 PM Marcin Jaczewski wrote:
>
> Image we add new contextual keyword like:
> ```
> class Type arg_destructor_in_callee
> {
> };
> ```
> Now when the function `void foo(Type arg)` is called, the object `arg`
> will be destroyed
> in the body of `foo` not by the caller. This will make for compiler
> easy to see if object was
> moved before the destructor call and then if the destructor was inlined
> then it could remove it all. This will work great with `bitcopies` or
> `Trivially Relocatable` types.


The following program can be toggled to "destroy in caller" or
"destroy in callee" by setting the global boolean "destroy_in_callee"
to true or false.

I realise that the following code won't give you the optimisation
you're looking for, but is it at least the behaviour you're going for?

// Step 1: Have a global boolean to specify destroy by caller/callee
bool constexpr destroy_in_callee = true;

#include <iostream>

// Step 2 : Write a sample dummy class that says hello and goodbye
struct MyClass {

    bool is_valid = true;

    MyClass(char const* = nullptr)
    {
        std::cout << "Constructing object" << std::endl;
    }

    MyClass(MyClass &&temp)
    {
        temp.is_valid = false;
    }

    ~MyClass(void)
    {
        if ( false == is_valid ) return;

        std::cout << "Destroying object" << std::endl;
    }
};

// Step 3: Write a template function to get an L-value reference to a
// temporary object
template <class T>
T &LvalueRef(T &&arg)
{
    return arg;
}

#include <optional>

// Step 4: Write a preprocessor macro to create a temporary
// object of type 'optional' from a temporary.
#define ARG(temp) LvalueRef(std::optional<decltype(temp)>( \
                              std::move(temp) ))

// Step 5: Write a function that can either do "destroy by caller"
// or "destroy by callee"
void SomeFunction(std::optional<MyClass> &arg)
{
    // I have the choice now whether the string
    // gets destroyed in this function or in
    // the calling function.

    if constexpr ( destroy_in_callee ) arg.reset();
}

int main(void)
{
// Step 6: Call the function and check where the temporary is destroyed

    SomeFunction( ARG(MyClass(nullptr)) ),
        (std::cout << "Hello again from Main" << std::endl);

    std::cout << "Last line in body of Main" << std::endl;
}


This program will print either:

Constructing object
Hello again from Main
Destroying object
Last line in body of Main

or:

Constructing object
Destroying object
Hello again from Main
Last line in body of Main

Received on 2022-08-08 10:59:54