テンプレートの記述で分からないことがあります。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
こんた

テンプレートの記述で分からないことがあります。

#1

投稿記事 by こんた » 5年前

Visual Studio Express 2013でlistクラスのソースを見たいたのですが

listクラスの実装で、以下ののようなコンストラクタのコードがありました。

コード:

template<class _Iter,
	class = typename enable_if<_Is_iterator<_Iter>::value,
		void>::type>
	list(_Iter _First, _Iter _Last)
	: _Mybase()
	{	// construct list from [_First, _Last)
	_Construct(_First, _Last);
	}
この"class = typename ~"という書き方を初めて見たのですが
これはどういった動作をするものなのでしょうか。
詳しく分かる方いましたら教えていただきたいです。
よろしくお願いします。

アバター
nullptr
記事: 239
登録日時: 8年前

Re: テンプレートの記述で分からないことがあります。

#2

投稿記事 by nullptr » 5年前

typenameは後続の識別子が型名である事を指定します。
テンプレート型Tがあるとき、T::typeと書くと、typeが型名なのかはコンパイラはその時点では判断できません。型名であることを明示するためにtypenameを書きます。
class = typename となっているのは、単にテンプレート引数名を省略しています。class T = 〜のTを省いた形です。
このテンプレート引数は実際に指定して使用する目的ではなく、SFINAEによってコンストラクタ呼び出しを解決するためのダミーのテンプレート引数です。
_is_iteratorは、MSVC内部実装なので憶測になりますが、おそらく引数の型がイテレータの要件を満たす場合、メンバ定数valueがtrueになる型と思われます。
そのbool定数をenable_ifに渡すことでSFINAEを操作しています。
もしイテレータの要件を満たさない場合はenable_ifにfalseが渡されます。enable_ifはfalseを渡された場合、メンバ型typeを定義しません。定義されていない型を実体化はできないので、本来はエラーになります。
しかしここでSFINAEが発動し、エラーではなくオーバーロード解決の候補からこのコンストラクタを排除するだけでエラーにはなりません。
結果として、このコンストラクタを呼び出せるのは引数の型がイテレータの要件を満たす場合のみになります。
 
 
✜ で C ご ✜
: す + 注 :
¦ か + 文 ¦
?
Is the は :
order C++? ✜
     糸冬   
  ――――――――
  制作・著作 NHK
 
 

こんた

Re: テンプレートの記述で分からないことがあります。

#3

投稿記事 by こんた » 5年前

詳しい解説ありがとうございます。
おかげさまでこの書き方について理解することができました。
テンプレートにこのような引数の型を限定できるテクニックがあるのを初めて知りました。

アバター
nullptr
記事: 239
登録日時: 8年前

Re: テンプレートの記述で分からないことがあります。

#4

投稿記事 by nullptr » 5年前

一応言っておきますが、かなり上級者の、こういうライブラリ実装者向けのテクニックです。
真似をするなど、迂闊に手を出したりはしない事をお勧めします。typenameを知らない段階で扱えるものではありませんので。
 
 
✜ で C ご ✜
: す + 注 :
¦ か + 文 ¦
?
Is the は :
order C++? ✜
     糸冬   
  ――――――――
  制作・著作 NHK
 
 

閉鎖

“C言語何でも質問掲示板” へ戻る