visual c++で使えるc++11

96
Visual C++ でででで C++11 nekko1119

Upload: nekko1119

Post on 28-May-2015

21.386 views

Category:

Documents


7 download

DESCRIPTION

身内向けですがせっかく作ったので。 土日に深夜のテンションで作ったので抜け漏れ誤字脱字だらけだと思います…

TRANSCRIPT

Visual C++ で使える C++11

nekko1119

身内向けです。 Visual C++で使える C++11の機能を、言語機能、ライブラリに分けて紹介します。

紹介する機能は私が独断と偏見で選んだ一部です。全て紹介するわけではありません。

コンパイラやライブラリのバグや部分対応までいくと作業量大変なのでそこら辺は触れません

内容の正しさには気をつけていますが間違えている可能性もあります。

まえがき

サンプルコードは暗黙に必要なヘッダのインクルード、 using namespace std;をしています。

また、イメージとしてのサンプルで、実際には動かないコードもあります。

ライブラリの初出は所属する名前空間が std::tr1ではなく stdになった初めてのバージョンとします

まえがき

Visual C++ 10.0 (Visual Studio 2010)

VC10

Visual C++ 11.0 (Visual Studio 2012)

VC11

Visual C++ 11.0 Community Technology Preview (Visual Studio 2012)

VC11CTP

Visual C++ 12.0 Preview (Visual Studio 2013 Preview)

VC12PR

Visual C++ 12.0 (Visual Studio 2013)

VC12

Visual C++ 12.0 Community Technology Preview (Visual Studio 2013)

VC12CTP

このスライドでは以下のように表記します

2013年 8月時点での細心のバージョンはVC12PRです。

それ以降のバージョン (VC12, VC12CTP)は公式で公開されている開発の予定です

Visual C++のバージョンについて

言語機能

変数の型を右辺式より推論する修飾子はつかない C/C++03までの自動変数を表す autoと互換性がなくなった

auto(VC10)

template <class F, class G, class T>void call(const F& f, const G& g, const T& t) { const auto& temp = f(t); g(temp);}

int main() { auto f = [](int n){return n * n;}; auto g = [](int n){return n + n;}; cout << call(f, g, 10) << endl;}

ヌルポインタを表すリテラル NULLはマクロで 0に置換され、数値と曖昧となる場合がある

nullptr(VC10)

void func(int){}void func(int*){}

int main() { func(10); func(nullptr);}

戻り値を宣言の後ろに記述できる後述の decltypeと合わせるとより便利

戻り値の後置 (VC10)

//int型を返す関数の宣言int hoge();auto foo() -> int;

//void (int)型の関数ポインタを返す関数の宣言void (*f())(int);auto g() -> void (*)(int);

式から型を推論する

decltype(VC10)

template <class T, class U>auto plus(const T& t, const U& u) -> decltype(t + u) { return t + u;}

int main() { vector<double> v; v.push_back(plus(10, 10.0)); const decltype(v) u = v;}

コンパイル時に assertチェックが出来るコンパイル時にチェックできるのは型とコンパイル時定数の 2つ

static_assert(VC10)

int main() { static_assert(sizeof(long) >= 8, "64bit以上環境が必要です "); static_assert(_MCV_VER >= 1600, "VC++10.0以上の VC++コンパイラでなければなりません ");}

従来の参照は正確には左辺値参照右辺値への参照ができるようになった機能としてはこれだけだが、本質は別にある。今回は機能紹介が目的なので省略

右辺値参照 (VC10)

int main() { int a = 10; int& lval_ref = a; //int& ng = 10; int&& rval_ref = 10; //int&& ng = a; const int& clval_ref1 = a; const int& clval_ref2 = 10;}

その場に無名の一時関数オブジェクトを生成する戻り値の省略可能変数のコピーキャプチャ、参照キャプチャ可能

ラムダ式 (VC10)

int main() { vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; vector<int> result; int border = 5; copy_if(v.begin(), v.end(), back_inserter(result), [&border](int it) { return it > border; });}

enumの前方宣言が可能になった要素の整数型を指定できるようになった要素の最後にカンマが付いても良くなった

enum(VC11)

enum weekend : unsigned short;void disp_weekend(weekend w);

enum weekend : unsigned short { SATURDAY, SUNDAY,};void disp_weekend(weekend w) { if(w == SATURDAY) { cout << "SATURDAY" << endl; } else { cout << "SUNDAY" << endl; }}

int main() { dips_weekend(SATURDAY); }

enumにスコープができた暗黙の型変換を禁止する

enum class(VC11)

enum class traffic_light : unsigned int { RED, YELLOW, BLUE};

int main() { traffic_light tl = traffic_light::RED; unsigned int i = static_cast<unsigned int>(tl);}

従来の for文は強いて言うならインデックス for文と言える

範囲ならば何でも、範囲全体を反復処理する

範囲 for文 (VC11)

int main() { for (const auto& it : {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) { if(it % 5 == 0) { cout << "buzz\n"; } else if (it % 3 == 0) { cout << "fizz\n"; } else { cout << it << endl; } }}

クラス、または仮想関数に final指定ができるクラスに指定した場合、そのクラスを基底クラスにすることができなくなる

仮想関数に指定した場合、その仮想関数をオーラーライドできなくなる

final(VC11)

class hoge final {};class foo : hoge {}; //エラー

class base { virtual void func() final {}};

class derived : base { virtual void func() {}//エラー};

オーバーライドの意図を明確にするためにできたタイポやオーバーライドのつもりになっているミス (気づきにくい )をエラーとして検出できる

override(VC11)

class hoge { virtual void func1() const {} virtual void func2() const {} void func3() {}};

class foo : hoge { virtual void fumc1() const override {} //エラー virtual void func2() override {} //エラー virtual void func3() override {} //エラー};

引数が 1つのコンストラクタは以前から暗黙な型変換を抑制する explicit指定ができた

型変換演算子にも explicit指定ができるようになった

明示的な型変換演算子 (VC11CTP)

class integer {public: explicit integer(int in) : value_(in) {} explicit operator int() const {return value_;}private: int value_;};

int main() { integer n(42); int m = static_cast<int>(n);}

今まではクラステンプレートにはデフォルトテンプレート引数が指定できたが、関数では無理だった (オーバーロードで同様のことが実現できるため )が、できるようになった

関数テンプレートのデフォルトテンプレート引数 (VC11CTP)

template <class T, class D = default_delete<T>>unique_ptr<T, D> make_unique(T* p, D d = D()) { return {p, forward<D>(d)};}

コンストラクタから同クラスの他のコンストラクタを呼び出すことが可能になる

処理を1ヶ所に纏められる

委譲コンストラクタ (VC11CTP)

class point_xy {public: point_xy() : point_xy(0, 0) {} point_xy(int x, int y) : x_(x), y_(y) {}

private: int x_; int y_;};

今まで引数無しコンストラクタ構文での初期化は関数宣言とみなされたり、初期化リストは配列型や POD型にしか適用できなかった。それらの制限を無くし統一された初期化構文 (初期化リスト構文の拡張 )で初期化できるようになった

統一された初期化構文(VC11CTP)

int main() { string str1{"Hello"}; string str2 = {"World"}; string str3{}; stirng str4 = {};

pair<int, int> p1{10, 20}; pair<int, int> p2 = {10, 20};}

任意の型の引数を任意個取ることができるクラス/関数テンプレートを作ることができる。

Cの可変長引数と比べて型安全である

可変長テンプレート引数(VC11CTP)

void print(){}

template <class T, class... Args>void print(const T& t, Args&&... args) { cout << typeid(T).name() << "\t:\t" << t << endl; print(args...);}

int main () { print("hoge", 42, 'c', 3.14, true);}

初期化リストに専用の型が出来た。これを引数にとるコンストラクタを定義することでユーザー定義型でも初期化リストが使えるようになった。

初期化リスト (VC12PR)

int sum(initializer_list<int> li) { return accumulate(li.begin(), li.end(), 0);}

template <class T, class U>pair<T, U> create_pair(T t, U u) { return {t, u}; //どちらかと言うと統一された初期化構文}

int main() { auto result = sum({9, 8, 7, 6}); auto p = create_pair("hello", 3.14); vector<double> v = {1.0, 2.0, 3.0};}

非静的データメンバを宣言と同時に初期化出来る C#などでは普通にできるコンストラクタで初期化すると上書きされる

メンバ初期化子 (VC12)

class person {public: person(const string& name, int age) : name_(name), age_(age) {} int age() const {return age_;} const string& name() const {return name_;}private: string name_ = "noname"; int age = -1;};int main() { person p; assert(p.age() == -1); person p2{"tom", 20}; assert(p.name() == "tom");}

コンパイラによって自動生成される関数が既定の動作であることを明示する

自動生成される関数へのdefault指定(VC12)

class hoge {public: hoge() = default; hoge(const hoge&) = default; ~hoge() = default; hoge& operator=(const hoge&) = default; //VC12の時点で move ctor/assignは自動生成されない};

望まない型変換や関数テンプレートのインスタンス化を抑止できる

自動生成される関数の生成を抑止できる

関数の delete指定 (VC12)

template <class T>void f(){}

//char型だけはダメtemplate <>void f<char>() = delete;

//long longより小さい型はダメvoid g(long long){}void g(long) = delete;

class hoge {public: hoge(const hoge&) = delete; hoge& operator=(const hoge&) = delete; //newで割り当てられないようにする void* operator new(size_t) = delete;};

typedefは型にしか別名をつけられないテンプレートに対する別名を usingを用いた構文で可能にした

usingを用いた構文で型にも別名を付けられる

別名テンプレート (VC12)

int add(int, int){}int sub(int, int){}

template <class T>using my_vector = vector<T, my_allocator<T>>;

int main() { using func_t = int (*)(int, int); my_vector<func_t> v = {add, sub};}

今までは暗黙にコンパイラに自動生成される関数はコンストラクタ、コピーコンストラクタ、コピー代入演算子、デストラクタの 4つだったがC++11ではムーブコンストラクタ、ムーブ代入演算子の 2つが増え、全部で 6つになった

サンプル無し

ムーブコンストラクタ・ムーブ代入演算子の自動生成 (VC12CTP)

オブジェクトが左辺値か右辺値かによってメンバ関数を呼び分けられるようになる

メンバ関数の参照修飾子 (VC12CTP)

struct hoge { void func() & { cout << "lvalue\n"; } void func() && { cout << "rlvalue\n"; }};

int main() { hoge h; h.func(); hoge().func();}

ユーザーが任意の型のリテラルを表すサフィックスを定義できる

ユーザー定義リテラル(VC12CTP)

string operator ""_s(const char* str, size_t size) { return {str, size};}

int main() { cout << "hello"_s.size() << endl;}

変数や関数がコンパイル時定数、コンパイル時計算可能である (結果として副作用がなく、参照透過性があることを保証している )ことを表す

constexpr(リテラル型とコンストラクタ除く )(VC12CTP)

constexpr int factorial(int n) { return n == 0 ? 1 : n * factorial(n - 1);}

int main() { array<int, factorial(4)> ar;}

関数が例外送出するか有無を指定できる式が例外を投げるか判定できる演算子

noexcept(VC12CTP)

class integer {public: integer(int value) : value_(value) {} int get() const noexcept {return value_;}private: int value_;};

int get(const integer& in) noexcept(noexcept(in.get())) { return in.get();}

int main() { integer n{42}; cout << get(n) << endl;}

alignof 変数や型のアライメントを取得する alignas 変数宣言の際、アライメントを指定する

alignof/alignas(VC12CTP)

int main() { alignas(int) unsigned char c[32]; alignas(4) int a; constexpr int int_align = alignof(int);}

ローカルクラス、無名クラスをテンプレート引数にする (VC10)

生文字リテラル (VC11CTP)二重になった山閉じ括弧の解釈 (VC8)

その他Visual C++で対応しているC++11の機能

C++11 VC++の書き方 バージョン

alignas(x) __declspec(align(x)) VC7

alignof(T) __alignof(T) VC7

thread_local __declspec(thread) VC10

[[noreturn]] __declspec(noreturn) VC7

独自拡張としてある機能

制限を無くした union属性 char16_t/char32_t inline namespace継承コンストラクタ thread_local Unicode文字列リテラルリテラル型に対する constexpr

VC12CTP以降になるC++11の機能

ライブラリ

始めに新しく登場したヘッダを紹介します。次に既存のヘッダに追加されたクラス、関数、型など紹介します

全て紹介するわけではありません各クラスのメンバについては触れません関数などのオーバーロードや事前 /事後条件や計算量や引数 /戻り値型の要求などについては触れません

まえがき

組み込みの配列型に STLコンテナのインターフェイスを持たせたクラス

固定長シーケンスコンテナ

組み込み配列とパフォーマンスは同じ

<array>(VC10)

ビット数が規定された整数型の typedefや、マクロを定義している

intN_t(Nビットサイズの符号あり整数型 ) uint_leastN_t(少なくとも Nビットサイズのある符号なし整数型 )

PTRDIFF_MAX(std::ptrfiff_tの最大値 )など

<cstdint>(VC10)

単方向リスト (listは双方向リストで、ノードに 2つのポインタを持つが、こちらは 1つ )

C言語で単方向リストを実装する場合と比べて、空間計算量も時間計算量もゼロオーバーヘッドであるよう設計されている

<forward_list>(VC10)

正規表現処理を行うクラス、関数が定義されている

正規表現のパターンを表した regex、マッチした結果を格納するmatchを使う     

<regex>(VC10)

文字コード変換を行う

ライブラリはあるが肝心の Unicodeリテラルやchar32_tなどに VCが対応してないので余り意味が無い

<codecvt>(VC10)

擬似乱数を扱うための、擬似乱数生成器、分布生成器、真の乱数生成器、シード数列などが定義されている

mt19937(パラメータ定義済み 32bitメルセンヌツイスターエンジン )や、 linear_congruential_engine(線形合同法エンジン )などの擬似乱数生成器、 uniform_int_distribution(一様整数分布生成器 )、 normal_distribution(正規分布生成器 )などがある

<random>(VC10)

型の特性、操作を行うメタ関数が定義されている

conditional(コンパイル時条件式 )、 is_same(2つの型が同じ型か判定する )、 coomon_type(共通の型を取得する )などがある

<type_traits>(VC10)

type_infoを連想配列のキーとして使えるように比較演算子などを定義している

<type_index>(VC10)

pairが 2つの型の組みを表すが、 tupleは任意個の型を値を保持できる

型リスト、無名構造体という見方もできる

要素は std::get関数を使う

<tuple>(VC10)

OSが出力するエラーを扱う機能を提供する

主にハードウエアやプログラム外でのエラーを通知する

<system_error>(VC10)

setと比べ、キーの順序ではなくキーの hash値に基いて格納される連想配列

ソートはされておらず、順序は有意ではないが検索が setよりも高速なため、ソートされている必要がないのならこちらを使うと良い

<unordered_set>(VC10)

mapと比べ、キーの順序ではなくキーの hash値に基いて格納される連想配列

ソートはされておらず、順序は有意ではないが検索がmapよりも高速なため、ソートされている必要がないのならこちらを使うと良い

<unordered_map>(VC10)

vector<string>のような要素とコンテナで両方にメモリ確保が必要になった場合、コンテナと要素で同じアロケータからメモリ確保するためのアロケータアダプタを提供する。

<scoped_allocator>(VC11)

有理数 (分数 )の定数を表すクラス

単位として使われるための typedefがある

四則演算、比較演算もある

<ratio>(VC11)

時間に関するライブラリ

std::chrono名前空間に定義

時間の任意の精度・表現で取得、計算、単位変換など行える

<chrono>(VC11)

ユーザー定義型が初期化リストで初期化できるようにするためのクラスが定義されている

イテレータを使って要素を取得する

<initializer_list>(VC11CTP)

マルチスレッドプログラミングをするための基本的な機能を提供する

スレッドを生成、終了することができる

<thread>(VC11)

変数へのスレッド間でデータをやり取りするための基本的な操作であるアトミック操作を提供する。

分解不能読み書きが行える。マルチスレッドプログラミングについて熟知していればmutexを用いるよりパフォーマンスが向上する可能性があるが、扱いが難しく逆にパフォーマンスが劣化する可能性もあるので、mutexのパフォーマンスが問題にならない限り使用しなくて良い

<atomic>(VC11)

スレッド間で安全にデータをやり取りするための排他制御を提供する

排他制御mutex、それを RAIIで扱えるlock_guard、指定された関数を 1度だけ呼び出す call_onceなどがある

<mutex>(VC11)

マルチスレッドプログラミングのデザインパターンの 1つである future/promiseパターンを実現する機能を提供する

データや例外を設定する promise、データや例外を取得する future、 future/promiseを簡単に行えるようラップした asyncなどがある

<future>(VC11)

並行キューを実現する機能を提供する

特定のイベント、条件を満たすまでスレッドの実行を待機させる。基本的なスレッド同期の仕組み

<condition_variable>(VC11)

面倒なので数が多いので内容の説明はせず、列挙だけしていきます

<ヘッダ名>(C++11のクラス、関数が追加された VCのバージョン )

既存ヘッダの追加クラス、関数

all_of, any_of, none_of find_if_not copy_n, copy_if move, move_backward suffle is_partitioned partition_copy, partition_point is_sorted, is_sorted_until is_heap, is_heap_until minmax, minmax_element is_permutation

<algorithm>(VC10)

bitset◦ all

<bitset>(VC10)

LLONG_MIN, LLONG_MAX ULLONG_MAX

<climits>(VC10)

function, bad_function_call bind, is_bindexpression, is_placeholder,

placeholders::_1, placeholders_2, placeholders::_N, mem_fn

reference_wrapper, ref, cref hash

<functional>(VC10)

next, prev move_iterator begin, end

<iterator>(VC10)

numeric_limit◦ lowest, max_digits10

<limits>(VC10)

wstring_convert wbuffer_convert

<locale>(VC10)

iota

<numeric>(VC10)

type_info◦ hash_code

<typeinfo>(VC10)

deque◦ cbegin, cende, crbegin, crend◦ shrink_to_fit◦ emplace, emplace_back, emplace_front

<deque>(VC10)

list◦ cbegin, cende, crbegin, crend◦ emplace, emplace_back, emplace_front

<list>(VC10)

set◦ cbegin, cende, crbegin, crend◦ emplace, emplace_hint

multi_set◦ cbegin, cende, crbegin, crend◦ emplace, emplace_hint

<set>(VC10)

map◦ cbegin, cende, crbegin, crend◦ at◦ emplace, emplace_hint

multi_map◦ cbegin, cende, crbegin, crend◦ at◦ emplace, emplace_hint

<map>(VC10)

queue◦ emplace, swap◦ reference, const_reference

priority_queue◦ emplace, swap◦ reference, const_reference

swap

<queue>(VC10)

stack◦ emplace, swap◦ reference, const_reference

swap

<stack>(VC10)

vector◦ cbegin, cende, crbegin, crend◦ shrink_to_fit◦ emplace, emplace_back

<vector>(VC10)

basic_string◦ cbegin, cende, crbegin, crend◦ shrink_to_fit◦ pop_back, back, front

stoi, stol, stoul, stoll, stoull, stof, stod, stold

<string>1(VC10)

to_string to_wstring hash

<string>2(VC11)

nullptr_t(VC10) max_align_t(VC11)

<cstddef>(VC10, VC11)

bad_array_new_length(VC10) get_new_handler(VC11)

<new>(VC10, VC11)

unitilialized_copy_n

shared_ptr, unique_ptr, weak_ptr, enable_shared_from_this, bad_weak_ptr, owner_less, default_delete, addresso

make_shared, allocate_shared, static_pointer_cast, dynamic_pointer_cast, const_pointer_cast

pointer_safety, get_pointer_safety, declare_reachable, undeclare_reachable, declare_no_reachable, undeclare_no_reachable

<memory>1(VC10)

<memory>2(VC11) align, pointer_traits allocator_traits, allocator_arg_t,

allocator_arg, uses_allocator

forward, move(VC10) tuple_size, tuple_element, get(VC10) move_if_noexcept(VC11) declval, piecewise_constrcut_t,

piecewise_constrcut(VC11)

<utility>(VC10, VC11)

acos, asin, atan, acosh, asinh, atanh proj

<complex>(VC11)

nested_exception get_unexpected exception_ptr, current_exception,

rethrow_exception, make_exception_ptr throw_with_nested, rethrow_if_nested

<exception>(VC11)

HUGE_VALF, HUGE_VALL, INFINITY, NAN FP_INFINITE, FP_NAN, FP_NORMAL,

FP_SUBNORMAL, FP_ZERO FP_FAST_FMA, FP_FAST_FMAF,

FP_FAST_FMAL FP_ILOGB0, FP_ILOGBNAN MATH_ERRNO, MATH_ERREXCEPT math_errhandling

<cmath>(VC12PR)

DECIMAL_DIG FLT_EVAL_METHOD

<cfloat>(VC12PR)

<cfenv> <cinttypes> <ctgmath> <cstdbool> <cuchar>

VC12PR時点で対応していないC++11のライブラリ

<cmath>◦ asinh, acosh, atanh◦ exp2, expm1, log1p, log2◦ ilogb, logb, scalbn, scalbln◦ cbrt, hypot◦ erf, erfc, tgamma, lgamma◦ trunc, round, nearbyint, rint, lrint, llrint◦ remainder, remquo◦ copysign, nan, nextafter, nexttoward◦ fmax, fmin, fdim, fma◦ fpclassify, isfinite, isinf, isnan, isnormal, signbit◦ float_t, double_t,

※グローバル領域には存在する。 std名前空間に所属していない

VC12PR時点で対応していないC++11のライブラリ

<string>◦ u16string, u32string

VC12PR時点で対応していないC++11のライブラリ

C99や C++14などは一切触れておりません。

まさか 90Pも行くとは思っていませんでした…

誰得

大人しく cpprefjpや cplusplusを見るのがいいと思いましたまる

おわりに

おまけVisual C++の C++14対応

言語機能 &ライブラリ

一般化されたラムダキャプチャー (VC12CTP) auto指定での一般関数の戻り値の型推論

(VC12CTP)多相ラムダ (VC12CTP) decltype(auto)(VC12CTP) STLのユーザー定義リテラル対応 (VC12CTP)

言語機能

make_unique(VC12) <type_traits>の using alias(例えば

make_unsigned_t, decay_tなど )(VC12) begin()/cend()/rbegin()/rend()/crbegin()/

crend()(VC12)多相ファンクタ (VC12) async/await(VC12CTP)

ライブラリ

一般化された constexpr変数テンプレート軽量コンセプト dynarray

VC12CTP以降になるC++14の言語機能&ライブラリ