次のように、メンバー関数の型を推測することにより、「範囲」(またはコンテナー、シーケンス) の型を定義する特性クラスがあります。
template<class R>
struct range_type_traits
{
// "iterator": The type of the iterators of a range
using iterator = decltype(std::begin(std::declval<R>()));
// "value_type": The (non-reference) type of the values of a range
using value_type = typename std::remove_reference<decltype(*(std::declval<iterator>()))>::type;
};
私がこれを行う理由 (およびR直接 orのサブタイプを使用しない) は、メンバーを持ち、コンテナーにいくつかの/型を定義する必要がないstd::iterator_traits、テンプレート化されたライブラリ内の任意の型のコンテナーをサポートするためです。私の知る限り、ペアを使用してイテレータ インターフェイスを STL に公開しないコンテナのある種の「キー タイプ」を処理することはできません(例: has . You can access the key via .)。begin()value_typeiteratorstd::iterator_traitsstd::mapQMap<K,T>value_type = Titerator::key()
ここで、 に関数がある場合に条件付きで型key_typeiifを定義し、その戻り値の型を取得します。既存の特性クラスに定義を入れるだけでは、これをサポートしていないコンテナーのコンパイルは失敗します。iterator::key() constvalue_type
SFINAE を使用するとstd::enable_if、テンプレート関数を条件付きで有効にすることができます。既存のクラスを条件付きで拡張する方法/条件付きでサブタイプを定義する方法は?
このスケッチのようなもの:
template<class R>
struct range_type_traits
{
// "iterator": The type of the iterators of a range
using iterator = decltype(std::begin(std::declval<R>()));
// "value_type": The (non-reference) type of the values of a range
using value_type = typename std::remove_reference<decltype(*(std::declval<iterator>()))>::type;
ENABLE_IF_COMPILATION_DOES_NOT_FAIL {
// "key_type": The (non-reference) type of the keys of an associative range not using pairs in its STL-interface
using key_type = typename std::remove_reference<decltype(std::declval<iterator>().key())>::type;
}
};