C++26: Std:Indirect

jandeboevrie1 pts0 comments

, introduced by P3019R14 (Coe, Peacock, Parent). From the abstract: The class template indirect confers value-like semantics on a dynamically-allocated object. An indirect may hold an object of a class T. Copying the indirect will copy the object T. When an indirect is accessed through a const access path, constness will propagate to the owned object. The class template polymorphic confers value-like semantics on a dynamically-allocated object. A polymorphic may hold an object of a class publicly derived from T. Copying the polymorphic will copy the object of the derived type. When a…" />, introduced by P3019R14 (Coe, Peacock, Parent). From the abstract: The class template indirect confers value-like semantics on a dynamically-allocated object. An indirect may hold an object of a class T. Copying the indirect will copy the object T. When an indirect is accessed through a const access path, constness will propagate to the owned object. The class template polymorphic confers value-like semantics on a dynamically-allocated object. A polymorphic may hold an object of a class publicly derived from T. Copying the polymorphic will copy the object of the derived type. When a…" /> C++26: std::indirect | Sandor Dargo's Blog<br>Sandor Dargo's Blog<br>On C++, software development and books

HOME TAGS ARCHIVES BOOKS SPEAKING DAILY C++ WORKSHOPS HI... SUBSCRIBE

Blog 2026 08 12 C++26: std::indirect Post<br>Cancel

C++26: std::indirect<br>Sandor Dargo Aug 12 2026-08-12T00:00:00+02:00<br>5 min

C++26 adds two new vocabulary types in , introduced by P3019R14 (Coe, Peacock, Parent). From the abstract:<br>The class template indirect confers value-like semantics on a dynamically-allocated object. An indirect may hold an object of a class T. Copying the indirect will copy the object T. When an indirect is accessed through a const access path, constness will propagate to the owned object.<br>The class template polymorphic confers value-like semantics on a dynamically-allocated object. A polymorphic may hold an object of a class publicly derived from T. Copying the polymorphic will copy the object of the derived type. When a polymorphic is accessed through a const access path, constness will propagate to the owned object.

As you can tell, these two types are very close in spirit. They used to be two separate proposals — P1950 for indirect and P0201 for polymorphic — before being merged into one paper. Likewise, I originally planned to cover both in a single article, but it grew long enough that I decided to split it. This post covers std::indirect; the next one will cover std::polymorphic.<br>The problem with unique_ptr<br>std::unique_ptr has two fundamental issues when used as a member of a value-type class.<br>First, it breaks const propagation. unique_ptr::operator*() const returns a non-const T&. A const object can mutate its indirectly-stored members:<br>10<br>11<br>12<br>13<br>14<br>15<br>16<br>17<br>18<br>19<br>// https://godbolt.org/z/P7zdodhsd

struct Settings {<br>int volume = 50;<br>bool muted = false;<br>};

class Player {<br>std::unique_ptrSettings> settings_;<br>public:<br>Player() : settings_(std::make_uniqueSettings>()) {}

void mute() const {<br>settings_->muted = true; // compiles — mutates through const!<br>};

const Player p;<br>p.mute(); // const-correctness is broken

Second, it deletes copy operations. If Car should be copyable, you must write all five special member functions yourself. This is the tedious Rule of Five boilerplate that every C++ developer knows too well.<br>std::indirect — value semantics for heap-allocated objects<br>std::indirect is what std::unique_ptr would be if it had been designed for composite class members rather than ownership transfer. It owns a heap-allocated T and provides deep copies, const propagation, value-based comparison, and hashing — all the things you’d expect from a value type.<br>10<br>11<br>12<br>13<br>14<br>15<br>16<br>17<br>18<br>19<br>20<br>21<br>22<br>23<br>24<br>25<br>26<br>// https://godbolt.org/z/ePxb8E9Ko

struct Settings {<br>int volume = 50;<br>bool muted = false;

bool operator==(const Settings&) const = default;<br>auto operator(const Settings&) const = default;<br>};

class Player {<br>std::indirectSettings> settings_;<br>public:<br>Player() : settings_(std::in_place) {}

void mute() { settings_->muted = true; }<br>void set_volume(int v) { settings_->volume = v; }

int volume() const { return settings_->volume; }<br>bool is_muted() const { return settings_->muted; }

const Settings& settings() const { return *settings_; }

// ALL special member functions are compiler-generated.<br>// Copying deep-copies the Settings. Moving transfers it.<br>};

Note that mute() and set_volume() are non-const now — as they should be. If you tried to make them const, the compiler would stop you: indirect::operator->() const returns a const Settings*, so settings_->muted = true in a const method is a compile error:<br>error: assignment of member 'Settings::muted' in read-only object<br>settings_->muted = true; // this wouldn't compile!

The exact bug from the unique_ptr version is structurally impossible.<br>Let’s walk through what else indirect gives...

const object indirect class polymorphic settings_

Related Articles