Shoeisha Technology Media

CodeZine(コードジン)

特集ページ一覧

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

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

  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加
2013/03/28 14:00

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

目次

はじめに

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

 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++の文字列リテラルはバックスラッシュ:'\'によって特殊な文字を表現できます。\nで改行、\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);
}

  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

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

    C++に首まで浸かったプログラマ。 Microsoft MVP, Visual C++ (2004.01~2018.06) "だった"り わんくま同盟でたまにセッションスピーカやったり 中国茶淹れてにわか茶人を気取ってたり、 あと Facebook とか。 著書: - STL標準...

All contents copyright © 2005-2019 Shoeisha Co., Ltd. All rights reserved. ver.1.5