Skip to content

Instantly share code, notes, and snippets.

@jamboree
Last active April 28, 2020 13:31
Show Gist options
  • Save jamboree/ce039dbb58aeda3a57de4b8384629da3 to your computer and use it in GitHub Desktop.
Save jamboree/ce039dbb58aeda3a57de4b8384629da3 to your computer and use it in GitHub Desktop.
Practical object transition for C++
Document Number: P0XXXR0
Date: 2016-xx-xx
Reply-to: tongari95@gmail.com
Audience: EWG

Practical object transition for C++

1. Introduction

This proposal introduces the concept of object transition - a way to transit the object liftetime - into the core language.

2. Motivation

Rvalue-reference introduced a nice way in the C++ type system for move-semantic. While move operations could be much cheaper than their copy counterparts, they're still suboptimal in many common places.

A move operation typically involves 3 phases:

  • Copy the underlying data from the source
  • Reset the data of the moved-from object
  • Destruct the moved-from object afterward

Strictly speaking, the last phase is not part of a move operation, but it's an involved operation nevertheless due to the rule of object liftetime.

Because move-semantic is designed for broader usage, it doesn't make the moved-from object in detructed state, for example:

T a{...};
T b{std::move(a)};
a = f(...); // `a` can be reused here

Instead, the moved-from object is left in a "valid but unspecified state" after the move, so the liftetime of a continues and it can still be used from the user code.

However, in many cases (if not most), we don't use a anymore after it's moved, so such a valid-state guarantee becomes pure overhead.

And rember the C++ motto? You don't pay what you don't use. A more effiecent object transition should avoid the last 2 phases in a move operation.

That said, the benefit of object transition is not just for performance, it also helps:

  • Varaible renaming for code readibilty
  • Relaxed semantic for class invariant

which we're see in later examples.

3. Proposal

We propose the following type notation to the C++ type system to denote object transition:

  • T'& - Borrowing reference to T
  • T'&& - Transiting reference to T
  • T'(T'&&) - Revive constructor

Traditionally, the liftetime of an object in C++ is ended when its destructor is called. In this proposal, if an object is transited using the transit-operation, the liftetime of the transited object is not ended as the destructor is not called, instead, the liftetime continues on the new object.

Utility Functions

template<class T>
constexpr T'&& transit(T'& t)
{
    return static_cast<T'&&>(t);
}

template<class T>
constexpr T'&& claim(T& t)
{
    return static_cast<T'&&>(t);
}

// Cannot claim the ownership from a borrowed one
template<class T>
void claim(T'& t) = delete;

// forward & move remain the same

Type inference

T a;
{
    T'& b = a; // borrow the ownership from `a`
    b.doSomething();
    a.doSomething(); // error, the ownership of `a` is not returned yet
    // `b` return the ownership to `a`
}
a.doSomething(); // ok, the ownership is returned
{
    T'&& b = std::transit(a); // transit the ownership from `a`
    b.doSomething();
    a.doSomething(); // error, the ownership of `a` is transited
    // the lifetime of the bound object ends, i.e. b.~T() will be called
}
a.doSomething(); // error, cannot reference `a` anymore

template<class Ty>
void f(Ty&&);

T a, b;
f(T{}); // Ty = T'
f(a); // Ty = T&
f(std::move(a)); // Ty = T
f(std::transit(b)); // Ty = T'

Ownership level

There are 3 ownership levels - 0, 1, 2.

  • 0 - No ownership
  • 1 - On a variable with auto-storage or is an owning reference
  • 2 - On a owning reference in a revive constructor with the same token
struct Derived : Base
{
    T val;
    Derived'(Derived'&& other) // other has ownership level 2
      : Base(std::transit(other)), val(std::transit(other).val)
    {
        f(std::transit(other)); // error, cannot transit from ownership level 2
    }
};

Related works

P0023R0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment