SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

特集記事

「Visual C++ Compiler November 2012 CTP」で追加された6つの新機能

追加されるC++11の機能

  • X ポスト
  • このエントリーをはてなブックマークに追加

Delegationg Constructors:コンストラクタの移譲

 double型の実数部/虚数部を持つ複素数:dcomplexを定義します。コンストラクタは引数2つ/1つ/なしの3通り:

list-04
struct dcomplex {
  dcomplex(double re, double im) : real(re),  imag(im)  {}
  dcomplex(double re)            : real(re),  imag(0.0) {}
  dcomplex()                     : real(0.0), imag(0.0) {}
  double real;
  double imag;
};

 C++11ではコンストラクト時の初期化を、ほかのコンストラクタに移譲(丸投げ/横流し)できるようになりました:

list-05
struct dcomplex {
  dcomplex(double re, double im) : real(re),  imag(im)  {}
  dcomplex(double re)            : dcomplex(re,  0.0)   {} // dcomplex(double,doule) に移譲
  dcomplex()                     : dcomplex(0.0)        {} // dcomplex(double) に移譲
  double real;
  double imag;
};

 コンストラクト時の初期化がややこしい場合に重宝しそうです。

Uniform Initialization:統一された初期化

 ついさっきこしらえたdcomplexで変数をいくつか定義します:

list-06
  dcomplex dc2(1.2, 3.4);
  dcomplex dc1(5.6);
  dcomplex dc0; // えっ!?

 ...キモチ悪いよね。書式を揃えてdcomplex dc0();とは書けないんですよね。「dcomlexを返す引数なしの関数dc0」を意味しちゃいますからね。

 C++11では初期化に必要な引数を{}で囲む書式が導入されました:

list-07
  dcomplex dc2 { 1.2, 3.4 };
  dcomplex dc1 { 5.6 };
  dcomplex dc0 { };
  // ついでに他のも...
  int      i   { 7 };
  char     c[] { 'A', 'B', 'C', 'D', 'E' };

 ここまでできるなら、ついでにvector<int> v { 1, 2, 3 }; と書きたいところですが、現時点では残念ながら無理なんです。というのも、{ 1. 2. 3 } は初期化リスト:initializer_list<int> と解釈されます。今回のCTPではライブラリの変更は行われていないので、initializer_list<int>を受けるコンストラクタがないのです。ライブラリのupdateまでは:

list-08
  auto data { 1, 2, 3 };
  vector<int> v { data.begin(), data.end() };

でガマンしてくださいな。

Variadic Template:可変長テンプレート

 本CTPの最大の目玉です。テンプレート引数の個数が可変の関数/クラステンプレートが書けるようになりました。Variadic Templateをきちんと語るにはすごく長ぁいおハナシになっちゃうので、ここではさらっと概説しておきます。

 まずは関数テンプレート。任意の型/個数の引数を取り、各引数の型と値とをプリントする関数printを定義してみます:

list-09
void print() {}

template<typename Tcar, typename ...Tcdr>
void print(Tcar head, Tcdr... tail) {
  std::cout << typeid(head).name() <<':' << head << std::endl;
  print(tail...);
}

 ...何コレ?って感じでしょ?

 print(1, 'A', 2.3, "BC")が呼ばれると、コンパイラはprint<int,char,double,const char*>とみなします。このときテンプレート引数Tcarはint,Tcdrは「char,double,const char*のパック(カタマリ)」と解釈されます。...Tcdrの...がパック(カタマリ)を意味するわけね。

 関数printに引き渡された引数についてもheadが1、tailが「'A', 2.3, "BC" のパック」です。関数print内ではheadの型名と値をcoutに出力したのち print(tail...)しています。

 tail...の...はパックを展開する、つまりカタマリをほぐすことを表し、print('A', 2.3, "BC")が呼び出されます。すると今度はTcarはchar,Tcdrは「doule,const char*のパック」と解釈されて以下同文、パックのナカミが1つずつ減って空になるまで再帰的に呼び出されます。といってもホントに再帰的にprint自身が呼び出されるわけではありません。関数テンプレートですからテンプレートの型/数が異なれば異なる関数となります。なのでしいて言えばテンプレート引数の異なる"同じ名前の関数"が呼び出されるわけです。

 アタマのvoid print() {}はパックが空のとき「何もしない」を定義するためのものです。

 このように可変長テンプレートは、再帰的な定義によって実装します。クラステンプレートも同様に再帰的な定義です。例えば複数の型の組:tupleの場合だと:

list-10
template<int N, typename ...T> 
struct tuple_data;

template<int N> 
struct tuple_data<N> {
};

template<int N, typename Tcar, typename ...Tcdr>
struct tuple_data<N, Tcar, Tcdr...> : public tuple_data<N+1, Tcdr...> {
  Tcar value;
};

template<typename ...T> struct tuple : public tuple_data<0, T...> {
};

 ...なにやってんだかさっぱりワカンネーですね。この定義によってtouple<int,char,long>の場合

  tuple_data<3>               {}
  tuple_data<2,long>          { long value; }
  tuple_data<1,char,long>     { char value; }
  tuple_data<0,int,char,long> { int  value; }

を積み重ねて(順に継承して)touple<int,char,long>が作られます。

 以上、Visual C++ Compiler November 2012 CTPで追加されたC++11の新機能でした。

 Variadic Templateは、強力ながら相当にややこしいカラクリです。今回はこれくらいで勘弁してください。いつかどこかできちんと解説したいと考えています。

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
特集記事連載記事一覧

もっと読む

この記事の著者

επιστημη(エピステーメー)

C++に首まで浸かったプログラマ。Microsoft MVP, Visual C++ (2004.01~2018.06) "だった"りわんくま同盟でたまにセッションスピーカやったり中国茶淹れてにわか茶...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/7061 2013/03/28 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング