namespace std {
template <class T, class Allocator = allocator<T>>
class polymorphic;
namespace pmr {
template <class T>
using polymorphic = std::polymorphic<T, polymorphic_allocator<T>>;
}
}
概要
std::polymorphicクラスは、動的確保したオブジェクトに値の意味論をもたせつつ、Tから派生した任意の型のオブジェクトを多態的に保持できる型である。
std::indirectクラスが単一の型Tのオブジェクトを保持するのに対し、std::polymorphic<T>クラスはTを基底とする派生型のオブジェクトを保持できる。値型としての性質はstd::indirectクラスと共通している:
- ディープコピー:
std::polymorphic<T>クラスのオブジェクトをコピーすると、実際に保持している派生型のオブジェクトが、その派生型のコピーコンストラクタによって複製される(型消去をとおした仮想ディスパッチが用いられる) constの伝播:constなアクセス経路から所有オブジェクトにアクセスすると、所有オブジェクトにもconstが伝播する- 不完全型のサポート: テンプレートパラメータ
Tは不完全型でもよい
これらの性質によって、std::polymorphicクラスは多態的な性質をもつクラスのメンバ変数として適しており、コンパイラによる特殊メンバ関数の自動生成と協調して動作する。
所有オブジェクトを持たない状態を「無効値状態 (valueless state)」と呼ぶ。std::polymorphicクラスが無効値状態になるのは、ムーブ後に空となった場合のみである。無効値状態のオブジェクトに対するoperator*やoperator->の呼び出しは未定義動作を引き起こす。無効値状態かどうかはvalueless_after_move()で判定できる。
保持する型の集合が既知である場合は、std::variantやindirect<std::variant<...>>の使用を検討するとよい。
テンプレートパラメータ制約
AllocatorはCpp17Allocator要件を満たすこと。allocator_traits<Allocator>::value_typeがTと同じ型であること
適格要件
- 以下のいずれかの場合に、プログラムは不適格となる
Tがオブジェクト型でない- 配列型である
- (CV修飾された)
std::in_place_tである - (CV修飾された)
std::in_place_type_tの特殊化である - CV修飾された型である
std::polymorphicの明示的特殊化・部分特殊化をユーザーが宣言した場合、動作は未定義である
メンバ関数
構築・破棄
| 名前 | 説明 | 対応バージョン |
|---|---|---|
(constructor) |
コンストラクタ | C++26 |
(destructor) |
デストラクタ | C++26 |
operator= |
代入演算子 | C++26 |
値へのアクセス
| 名前 | 説明 | 対応バージョン |
|---|---|---|
operator* |
所有するオブジェクトへの参照を取得する | C++26 |
operator-> |
所有するオブジェクトのメンバへアクセスする | C++26 |
valueless_after_move |
無効値状態かどうかを判定する | C++26 |
その他
| 名前 | 説明 | 対応バージョン |
|---|---|---|
get_allocator |
アロケータを取得する | C++26 |
swap |
他のpolymorphicオブジェクトと値を交換する |
C++26 |
メンバ型
| 名前 | 定義 | 対応バージョン |
|---|---|---|
value_type |
T |
C++26 |
allocator_type |
Allocator |
C++26 |
pointer |
allocator_traits<Allocator>::pointer |
C++26 |
const_pointer |
allocator_traits<Allocator>::const_pointer |
C++26 |
非メンバ(Hidden friends)関数
| 名前 | 説明 | 対応バージョン |
|---|---|---|
swap |
2つのpolymorphicオブジェクトを交換する |
C++26 |
例
#include <cassert>
#include <memory>
struct Shape {
virtual ~Shape() = default;
virtual int area() const = 0;
};
struct Square : Shape {
int side;
Square(int s) : side(s) {}
int area() const override { return side * side; }
};
int main()
{
// Shapeから派生したSquareを、値の意味論で多態的に保持する
std::polymorphic<Shape> a{std::in_place_type<Square>, 3};
assert(a->area() == 9);
// コピーは派生型(Square)のディープコピー
std::polymorphic<Shape> b = a;
assert(b->area() == 9);
}
出力
バージョン
言語
- C++26
処理系
- Clang: 22 ❌
- GCC: 16.1 ✅
- Visual C++: 2026 Update 2 ❌
関連項目
std::indirect単一の型を保持する値型std::variant既知の型集合から1つを保持する型std::unique_ptr多態的な所有権をもつが参照の意味論をもつスマートポインタ
参照
- P3019R14
indirectandpolymorphic: Vocabulary Types for Composite Class Design- C++26で
indirectとpolymorphicが追加された
- C++26で