GeezerVison is showing cpprefjp.github.io — constexpr仮想継承を許可 [P3533R2] - cpprefjp C++日本語リファレンス
最終更新日時:
2026年04月06日 10時14分31秒 (JST)
Akira Takahashi
が更新
履歴
編集
constexpr仮想継承を許可 [P3533R2](C++26)
このページはC++26に採用される見込みの言語機能の変更を解説しています。
のちのC++規格でさらに変更される場合があるため関連項目 を参照してください。
概要
C++26では、constexprの文脈で仮想継承が許可される。
これまで、constexprコンストラクタおよびデストラクタを持つクラスは仮想基底クラスを持つことができなかった。C++26ではこの制限が撤廃され、仮想継承を含むクラス階層でもコンパイル時の定数評価が可能になる。
struct Base {
constexpr virtual ~ Base () = default ;
};
struct Derived : virtual Base {
constexpr Derived () = default ; // C++26: OK (C++23以前: 不適格)
constexpr ~ Derived () = default ; // C++26: OK (C++23以前: 不適格)
};
constexpr Derived d {}; // OK
仕様
constexpr宣言の仕様にあった以下の制約が削除される:
(constexpr指定された対象が) コンストラクタまたはデストラクタである場合、そのクラスは仮想基底クラスを持たないこと
これにより、仮想基底クラスを持つクラスのコンストラクタおよびデストラクタにconstexprを指定できるようになる。
例
#include <cassert>
struct Common {
unsigned counter { 0 };
constexpr virtual ~ Common () = default ;
};
struct Left : virtual Common {
constexpr const unsigned & get_counter () const {
return counter ;
}
};
struct Right : virtual Common {
constexpr const unsigned & get_counter () const {
return counter ;
}
};
struct Child : Left , Right {};
int main () {
constexpr auto ch = Child {};
// 菱形継承でも仮想基底クラスのメンバは共有される
static_assert ( & ch . Left :: get_counter () == & ch . Right :: get_counter ());
}
出力
この機能が必要になった背景・経緯
C++のconstexpr機能は段階的に拡張されてきたが、仮想継承を含むクラスのコンストラクタ・デストラクタをconstexprにすることは禁止されたままだった。これはconstexprの文脈で許可されない最後の構文上の制限であった。
この制限は、標準ライブラリのconstexpr化を妨げる障害にもなっていた。特に、std::stringstream などのストリームユーティリティは仮想継承を使用しており、この制限によりコンパイル時に使用できなかった。また、<chrono> の例外型(chrono::nonexistent_local_time など)のconstexpr化も阻害されていた。
参照