次のように、メンバー関数の型を推測することにより、「範囲」(またはコンテナー、シーケンス) の型を定義する特性クラスがあります。
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_type
iterator
std::iterator_traits
std::map
QMap<K,T>
value_type = T
iterator::key()
ここで、 に関数がある場合に条件付きで型key_type
iifを定義し、その戻り値の型を取得します。既存の特性クラスに定義を入れるだけでは、これをサポートしていないコンテナーのコンパイルは失敗します。iterator
::key() const
value_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;
}
};