STL運用のC++技術(3)——テンプレート実参推定


STLはC++標準ライブラリの重要な構成部分の一つであり、多重化可能なコンポーネントライブラリだけでなく、アルゴリズムとデータ構造を含むソフトウェアフレームワークであり、C++汎用プログラミングの良い例でもある.STLには多くのC++の高度な技術が用いられている.テンプレート実参推定の運用を紹介する.主に『C++Primer』と『STLソース剖析』を参考にした.
STLはテンプレートテンプレートを用いて実現され,例えばそのアルゴリズムはいずれも関数テンプレートである.テンプレートは式または青写真であり、それ自体がクラスまたは関数ではなく、インスタンス化する必要があることを知っています.このプロセスはコンパイル期間中に完了し,コンパイラは伝達された実パラメータに基づいてパラメータのタイプを推定し,対応する関数をインスタンス化する.「C++Primer」の定義:関数実パラメータからテンプレート実パラメータのタイプと値を決定するプロセスをテンプレート実パラメータ推定(template argument deduction)と呼ぶ.以下にSTLのいくつかのアルゴリズムを示し,名前に簡単な修正を行い,一部のコードを省略した.
//   
template <class T>
inline const T& Min(const T& a, const T& b) {
  return b < a ? b : a;
}
//   
template <class T>
inline const T& Max(const T& a, const T& b) {
  return  a < b ? b : a;
}
以下で使用すると、コンパイラはMinの2つのバージョンをインスタンス化します.
int main()
{
	cout<<Min(1,2)<<endl;
	cout<<Min(1.2,3.2)<<endl;
	return 0;
}
inline const int& Min(const int& a, const int& b) {
  return b < a ? b : a;
}
inline const double& Min(const double& a, const double& b) {
  return b < a ? b : a;
}

上で紹介したのは比較的簡単で、具体的な内容は《C++Primer》を詳しく見ることができて、本文はただこれによって敷き詰めるだけです.前の記事「STLで運用されているC++技術(2)」では,反復器が指すデータ型を取得する際にテンプレート実パラメトリック推定メカニズムを用いず,埋め込み型別技術とテンプレート特化技術を用いた.なぜなら、戻り値のタイプを推定できないからです.ここで再びこのコードを貼り付けます.
//         
template <class Iter1, class Iter2, class T>  
inline void _iter_swap(Iter1 a, Iter2 b, T) {  
  T tmp = *a;  
  *a = *b;  
  *b = tmp;  
}  
//              
template <class Iter1, class Iter2>  
inline void iter_swap(Iter1 a, Iter2 b) {  
 _iter_swap(a, b, *a); //        
} 

         iter_swap関数はテンプレートの実パラメータ推定を用いて反復器が指すデータ型を取得する.しかし、この関数が最初の反復器のデータを返す場合、どうすればいいですか?テンプレートの実参推定は無力であり,埋め込み型別を利用して,以下のように定義すればよい.コンパイラにこれがタイプであることを伝えるためにキーワードtypenameを追加する必要があります.そうしないと、コンパイルは通過できません.
#include <iostream>
#include <vector>
#include <list>
using namespace std;

//   
template<class I>
struct Iterator_traits{
	typedef typename I::value_type value_type;
};
//       
template<class T>
struct Iterator_traits<T*>{
	typedef T value_type;
};
//        
template<class T>
struct Iterator_traits<const T*>{
	typedef T value_type;
};

//         
template <class Iter1, class Iter2, class T>  
inline void _iter_swap(Iter1 a, Iter2 b, T) {  
  T tmp = *a;  
  *a = *b;  
  *b = tmp;  
}  
//              
template <class Iter1, class Iter2>  
inline typename Iterator_traits<Iter1>::value_type //              
iter_swap(Iter1 a, Iter2 b) {  
 _iter_swap(a, b, *a); //       
 return *a;   
}  

int main()
{
	list<int> l;
	l.push_back(3);
	l.push_back(4);
	cout<<iter_swap(l.begin(),++l.begin())<<endl;
	return 0;
}
         
私はブログの文章の著作権を享有して、転載して出典を明記してくださいhttp://blog.csdn.net/wuzhekai1985