Sprout の破壊的変更 - constexpr コンテナのトレイト周りの刷新
Sprout C++ Library
Github https://github.com/bolero-MURAKAMI/Sprout
Sprout に大幅な破壊的変更が入りました。
ユーザコードにおいて、コンテナのトレイト関連を使用したコードは、新しいものに書き換えする必要があります。
また、ユーザ定義のコンテナをアダプトするコードも全面的に書き換えられます。
ヘッダ
-
- 旧 sprout/fixed_container/*
#include<sprout/fixed_container.hpp> #include<sprout/fixed_container/traits.hpp> #include<sprout/fixed_container/functions.hpp> #include<sprout/fixed_container/metafunctions.hpp>
-
- 新 sprout/container/*
#include<sprout/container.hpp> #include<sprout/container/traits.hpp> #include<sprout/container/functions.hpp> #include<sprout/container/metafunctions.hpp>
sprout/fixed_container/* は、ほぼ全て sprout/container/* に置き換えられます。
関数
sprout::begin や sprout::end などの基本的な機能も sprout/container/* に移動されました。
これらの動作自体は変わらないので、ユーザコードではインクルードするヘッダを切り替えるだけで済むでしょう。
トレイト
これまでは、コンテナ特性を検証したりユーザ定義のコンテナをアダプトするのに fixed_container_traits といくつかの特殊化用クラスを使用していました。
これからは、同じ目的で新たに整理された4つのトレイトが提供されます。
・container_traits (コンテナの基本特性を提供する)
・container_construct_traits (コンテナを構築する機能を提供する)
・container_transform_traits (コンテナを変形する機能を提供する)
・sub_container_traits (サブコンテナに関する機能を提供する)
-
- 旧 fixed_container_traits
template<typename Container> struct fixed_container_traits { /* container_traits に置き換えられる部分 */ typedef implementation-defined value_type; typedef implementation-defined iterator; typedef implementation-defined const_iterator; typedef implementation-defined reference; typedef implementation-defined const_reference; typedef implementation-defined size_type; typedef implementation-defined difference_type; typedef implementation-defined pointer; typedef implementation-defined const_pointer; static constexpr size_type fixed_size = implementation-defined; /* sub_container_traits に置き換えられる部分 */ typedef implementation-defined internal_type; /* container_construct_traits に置き換えられる部分 */ typedef implementation-defined clone_type; /* 廃止される部分 */ typedef implementation-defined fixed_container_type; };
-
- 新 container_traits
template<typename Container> struct container_traits { /* 基本的な型定義 */ typedef implementation-defined value_type; typedef implementation-defined iterator; typedef implementation-defined const_iterator; typedef implementation-defined reference; typedef implementation-defined const_reference; typedef implementation-defined size_type; typedef implementation-defined difference_type; typedef implementation-defined pointer; typedef implementation-defined const_pointer; /* コンテナの固定長サイズ */ static constexpr size_type static_size = implementation-defined; static constexpr size_type fixed_size(); };
sprout::container_traits は、コンテナの基本的な型定義とサイズを提供します。
基本的な型定義は、そのまま fixed_container_traits から container_traits に引き継がれます。
fixed_container_traits::fixed_size は、container_traits::static_size にリネームされます。
container_traits::fixed_size() の返す値は、static_size と同様です。
(ユーザ定義のコンテナをアダプトする場合)
以下の条件を満たす場合、ユーザ定義のコンテナは container_traits を特殊化する必要はありません。
・Container の内部で、これらの基本的な型定義と同じ名前が定義されている。
・std::tuple_size
-
- 新 container_construct_traits
template<typename Container> struct container_construct_traits { /* ディープコピーが行われる型 */ typedef implementation-defined copied_type; /* コンテナのディープコピーを行う関数 */ template<typename Cont> static constexpr copied_type deep_copy(Cont&& cont); /* 要素のリストからコンテナを構築する関数 */ template<typename... Args> static constexpr copied_type make(Args&&... args); /* 既存のコンテナを元にして、要素のリストからコンテナを構築する関数 */ template<typename Cont, typename... Args> static constexpr copied_type remake( Cont&& cont, typename sprout::container_traits<Container>::difference_type size, Args&&... args ); };
sprout::container_construct_traits は、コンテナを構築する機能を提供します。
copied_type は、fixed_container_traits::clone_type と同じ用途です。
例えば Container が他のオブジェクトの参照を保持するようなクラスであった場合、ディープコピーが正常に行われた結果の型を copied_type として定義する必要があります。
deep_copy は、コンテナのディープコピーを行います。
make は、要素のリストからコンテナの構築を行います。
remake は、既存のコンテナを元にして、要素のリストからコンテナの構築を行います。
なお、remake に渡される Cont 型は、Container と一致するとは限らないことに注意すべきです。
もし必要無ければ cont を無視することが出来ます。
これらの機能は、fixed_container における clone_functor, make_clone_functor, remake_clone_functor に相当するものです。
それらを使ってアダプトしていた場合、これからは container_construct_traits を使用してください。
(ユーザ定義のコンテナをアダプトする場合)
以下の条件を満たす場合、ユーザ定義のコンテナは fixed_container_traits を特殊化する必要はありません。
・Container のコピーコンストラクタをディープコピーとして扱って問題ない。
・Container が Aggregate で、かつ std::array と同じレイアウトである。
-
- 新 container_transform_traits
template<typename Container> struct container_transform_traits { /* 異なるサイズのコンテナを返すメタ関数 */ template<typename sprout::container_traits<Container>::size_type Size> struct rebind_size; };
sprout::container_transform_traits は、コンテナを変形するための機能を提供します。
rebind_size は、異なるサイズのコンテナを返すメタ関数です。
この機能は、fixed_container における rebind_fixed_size に相当するものです。
それらを使ってアダプトしていた場合、これからは container_transform_traits を使用してください。
(ユーザ定義のコンテナをアダプトする場合)
以下の条件を満たす場合、ユーザ定義のコンテナは container_transform_traits を特殊化する必要はありません。
・Container が template
-
- 新 sub_container_traits
template<typename Container> struct sub_container_traits { /* コンテナの内部型を返すメタ関数 */ template<typename Cont> struct internal; /* コンテナの内部型を取得する関数 */ template<typename Cont> static constexpr typename internal<Cont>::type get_internal(Cont&& cont); };
sprout::sub_container_traits は、サブコンテナに関する機能を提供します。
サブコンテナとは、何かコンテナを内包して別のコンテナのように振舞うアダプタをいいます。
サブコンテナの典型は sprout::sub_array です。
internal は、コンテナの内部型を返すメタ関数です。
get_internal は、コンテナの内部型を取得する関数です。
sub_container_traits が特殊化されていない場合、デフォルトで渡したコンテナ自身をそのまま返す。
これらの機能は、fixed_container における get_fixed_functor に相当するものです。
それらを使ってアダプトしていた場合、これからは sub_container_traits を使用してください。
(ユーザ定義のコンテナをアダプトする場合)
以下の条件を満たす場合、ユーザ定義のコンテナは sub_container_traits を特殊化する必要はありません。
・Container がサブコンテナでない場合。