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

CodeZine / 2013年3月28日 14時0分

 「Visual C++ Compiler November 2012 CTP」で追加されたC++11の6つの機能を紹介します。

■はじめに

 昨年の末、新たなVisual C++がリリースされたことにお気づきでしょうか。

Visual C++ Compiler November 2012 CTP(以下、Nov2012CTP)  CTPとはCommunity Technology Preview、要するにお試し版、正式なupdateまでの"つなぎ"なので実プロジェクトで使うわけにはいかないけども「次版の予告編として提供するから遊んでみてね。ついでに不具合見つけたら教えてくれるとうれしいな♪」的なリリースです。

 Nov2012CTPで提供されるのは、コンパイラ本体とヘッダが一本。Visual Studio 2012にadd-inする形式で、CTP単体ではインストールしても無意味です。Visual Studio 2012(無償版:Expressも可)がインストールされた環境で本CTPをインストールするとVisual C++プロジェクト・プロパティのプラットフォーム・ツールセットに追加され、こいつを選択することでコンパイラが切り替わります。



 ただし今回のCTPはホントにコンパイラ"だけ"であり、IDEやIntelliSenseは従来のまま。なので、構文エラーを示す波線がところどころに現れるのはご承知おきください。

 Nov2012CTPで追加されたのは、VC11(Visual C++ 2012)でサポートできてなかったC++11の機能の中から6つ:

Raw String Literals Explicit Conversion Operators Default template Arguments for Function Templates Delegating Constructors Uniform Initialization Variadic Templates  片っ端からざっくりと解説しましょうね。

■Raw String Literals:'生'の文字列リテラル

 C/C++の文字列リテラルはバックスラッシュ:'\'によって特殊な文字を表現できます。 で改行、\tでTabとかね。その代わり \ は\\ と表記しなければなりませんが、これが時として煩わしく感じることがあります。例えば正規表現。”バックスラッシュで囲まれた部分文字列”を見つけたいとき、これにマッチする正規表現は\\.*\\です。これを文字列リテラルで記述すると例えば:

regex re( "\\\\.*\\\\" );
 です。ちょっとウンザリしますね。C++11ではリテラルにRを接頭することでバックスラッシュによるエスケープを行わない'生'の文字列を書き下すことができます。

regex re( R"(\\.*\\)" );
 このように、R"(と)" で囲まれた文字列がリテラルとなり、改行やTab、引用符などもそのまま書き下せます。...それじゃリテラル中に )" を書きたい...そんなアナタのために、終端記号をユーザが指定できます。R"raw(abc"(def)"ghi)raw"のようにR"○×△(からはじめれば)○×△"が終端です。なるほどねー。

■Explicit Conversion operators:明示的な変換オペレータ

list-01
#include <iostream> using namespace std; class negative { public: negative(int v) : value_(v) {} operator bool() const { return value_ < 0; } private: int value_; }; int main() { negative neg(-3); cout << neg + 123 << endl; // えっ? }
 このコード、不思議なことにコンパイル/実行できちゃいます。class negativeであるbegとint値123とを+できるハズがないのに...。これはoperator bool()によってboolへの暗黙の型変換が行われ、bool値がint扱いされて+されるからなんですね。

 このような暗黙の型変換を抑止するため、変換オペレータを'explicit'で修飾できるようになりました。引数1つのコンストラクタをexplicit修飾することで暗黙のコンストラクトを抑止するのと同じです。explicitされた変換オペレータは明示的なキャスト(この例では(bool)negやstatic_cast<bool>(neg))が行われない限り、勝手に変換されることはなく、コンパイルエラーとしてくれます。

■Default Template Arguments for Function Templates:関数テンプレートにおけるデフォルト・テンプレート引数

 <algorithm>に定義された std::sort を用いてコンテナ内の要素をソートする関数を書くことにしましょう。引数はコンテナと比較オブジェクト(ファンクタ)、ただし比較オブジェクトが与えられないときはstd::less<コンテナ要素の型>を使います。従来ならこんな実装になるでしょうね:

list-02
template<typename Container, typename Pred> void sort_container(Container& container, Pred compare) { std::sort(begin(container), end(container), compare); } template<typename Container> void sort_container(Container& container) { std::sort(begin(container), end(container), std::less<typename Container::value_type>()); }
 関数テンプレートにデフォルト・テンプレート引数が許されないので、比較オブジェクトのアリ版とナシ版とを定義しています。C++11ではデフォルト・テンプレート引数がサポートされるため、こんなコードで実現できます。

list-03
template<typename Container, typename Pred = std::less<typename Container::value_type>> void sort_container(Container& container, Pred compare =Pred()) { std::sort(begin(container), end(container), compare); }


CodeZine

この記事に関連するニュース

トピックスRSS

ランキング