yohhoyの日記

技術的メモをしていきたい日記

std::destructibleコンセプト

C++20標準ライブラリstd::destructible<T>コンセプトに関するメモ。

ある型Tが「例外送出なしにデストラクト可能」と制約(constraint)するコンセプト。デストラクタは規定で暗黙のnothrow指定が行われるため*1、明示的にnothrow(false)指定を行わない限りあらゆるオブジェクト型が満たすコンセプトとなる。*2

std::destructibleコンセプトは、標準ヘッダ <concepts> 提供のオブジェクト関連コンセプトにより直接/間接的に包摂(subsume)される。

  • std::constructible_from
  • std::default_initializable
  • std::move_constructible
  • std::copy_constructible
  • std::movable
  • std::copyable
  • std::semiregular
  • std::regular

C++20 18.4.10, 18.4.11より引用(下線部は強調)。

1 The destructible concept specifies properties of all types, instances of which can be destroyed at the end of their lifetime, or reference types.

template<class T>
  concept destructible = is_nothrow_destructible_v<T>;

2 [Note: Unlike the Cpp17Destructible requirements (Table 32), this concept forbids destructors that are potentially throwing, even if a particular invocation of the destructor does not actually throw. -- end note]

1 The constructible_from concept constrains the initialization of a variable of a given type with a particular set of argument types.

template<class T, class... Args>
  concept constructible_from = destructible<T> && is_constructible_v<T, Args...>;

2016年頃のC++ Ranges拡張PDTS*3時点でも、Destructibleコンセプト*4はオブジェクトコンセプトにおける最も基本的なコンセプトと説明されていた。(PDF)N4622より一部引用(下線部は強調)。

19.4 Object concepts
1 This section describes concepts that specify the basis of the value-oriented programming style on which the library is based.

19.4.1 Concept Destructible
1 The Destructible concept is the base of the hierarchy of object concepts. It specifies properties that all such object types have in common.

template <class T>
concept bool Destructible() {
  return requires (T t, const T ct, T* p) {
    { t.~T() } noexcept;
    /*(snip)*/
  };
}

(snip)

19.4.2 Concept Constructible
1 The Constructible concept is used to constrain the type of a variable to be either an object type constructible from a given set of argument types, or a reference type that can be bound to those arguments.

template <class T, class ...Args>
concept bool __ConstructibleObject =
  Destructible<T>() && requires (Args&& ...args) { /*(snip)*/ };

template <class T, class ...Args>
concept bool Constructible() {
  return __ConstructibleObject<T, Args...> || /*(snip)*/
}

関連URL

*1:C++20 14.5/p8: "The exception specification for an implicitly-declared destructor, or a destructor without a noexcept-specifier, is potentially-throwing if and only if any of the destructors for any of its potentially constructed subobjects is potentially-throwing or the destructor is virtual and the destructor of any virtual base class is potentially-throwing."

*2:参照型(reference type)はオブジェクト型(object type)ではないが(C++20 6.8.1/p8)、std::is_nothrow_destructible メタ関数の定義より std::destructible コンセプトを満たす。(cv修飾された)void 型/関数型/要素数未定の配列型は、std::destructible コンセプトを満たさない。

*3:Preliminary Draft Technical Specification

*4:検討段階におけるコンセプト関連の言語仕様は、C++20現在のコンセプト仕様とは異なっている。またコンセプト命名規則はその後の(PDF)P1754R1採択により Destructible→destructible/Constructible→constructible_from へと変更されている。