「C++14」の版間の差分

提供: C++入門
移動: 案内検索
(ページの作成:「C++14 とは、C++11のマイナーバージョンアップとラムダ式などの機能追加を行われたバージョン版のC++です。 '''読み...」)
 
行28: 行28:
 
[[配列]]のサイズ(要素数)を実行時の値で指定できるようになります。
 
[[配列]]のサイズ(要素数)を実行時の値で指定できるようになります。
 
<syntaxhighlight lang="cpp">
 
<syntaxhighlight lang="cpp">
void f(int i) {
+
void f(std::size_t size) {
int a[i];//
+
int a[size]; // 実行時サイズの配列
 +
}
 +
</syntaxhighlight>
 +
Cとは、sizeofで値がとれないなど、細かい部分で互換性がありません。
 +
 
 +
クラス内で使用できないケースがあります。
 +
構造体内の動的配列は、 Variable Length Array In Structure(VLAIS) と呼ばれます。
 +
[[C++14]]の実行時サイズ配列は、VLAISをサポートしません。
 +
<syntaxhighlight lang="cpp">
 +
void f(std::size_t size) {
 +
struct {
 +
int a[size]; // GCC VLAIS, C++14 ではエラーになる
 +
} valis;
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>
C((とは、sizeofで値がとれないなど、細かい部分で互換性がありません。
 
 
=== 通常の関数の戻り値型の推論 ===
 
=== 通常の関数の戻り値型の推論 ===
 
[[ラムダ式]]と同様に、通常の関数でもreturn文から戻り値の型を推論できるようにします。
 
[[ラムダ式]]と同様に、通常の関数でもreturn文から戻り値の型を推論できるようにします。
行39: 行50:
 
auto f(){return 123;}; // 関数f()の定義で、戻り値の型は int となる。
 
auto f(){return 123;}; // 関数f()の定義で、戻り値の型は int となる。
 
int x = f();// x = 123;
 
int x = f();// x = 123;
 +
</syntaxhighlight>
 +
return文のオペランドの式から推定されます。
 +
 +
K&R Cは、関数の戻り値型を省略した場合、暗黙にint型として扱われました。
 +
<syntaxhighlight lang="c">
 +
f() { return 0.0; } // K&R C, int
 +
</syntaxhighlight>
 +
K&R Cの短絡的な型省略と[[C++14]]の型推論の違いは、[[C++14]]の戻り値の型推論機能は、関数本体のreturn文のオペランドの式を評価した結果の型であることです。
 +
=== decltype(auto) ===
 +
decltype(auto)は、戻り値型の推定に追加された機能です。
 +
 +
decltype(変数)で、変数の型と同じ型を指定できます。
 +
 +
<syntaxhighlight lang="cpp">
 +
auto a = 10; // int a = 10; と同義
 +
decltype(a) b; // int b; と同義
 +
std::vector<decltype<a> v; // std::vector<int> v; と同義
 
</syntaxhighlight>
 
</syntaxhighlight>
 
=== ジェンリックラムダ ===
 
=== ジェンリックラムダ ===
行46: 行74:
 
return a > b;
 
return a > b;
 
};
 
};
 +
</syntaxhighlight>
 +
 +
Varadic template parameter(パラメーターパック)も使用できます。
 +
<syntaxhighlight lang="cpp">
 +
auto f = [](auto ... args) {};
 +
f();
 +
f(0);
 +
f(0,1);
 +
f(0,1,2,3,4,5);
 
</syntaxhighlight>
 
</syntaxhighlight>
 
=== 一般化されたラムダキャプチャ ===
 
=== 一般化されたラムダキャプチャ ===
 +
[[C++11]]では、非staticデータメンバーは、コピーキャプチャできませんでした。
 
<syntaxhighlight lang="cpp">
 
<syntaxhighlight lang="cpp">
 
int x = 1;
 
int x = 1;
行91: 行129:
 
* コンセプトの軽量版
 
* コンセプトの軽量版
 
* テンプレートの型制約機能
 
* テンプレートの型制約機能
 +
 +
=== 数値区切り ===
 +
「数値区切り」とは、「数値リテラルを単一引用符で区切る」機能です。区切りの桁は、任意です。
 +
大きな数字は、区切りを入れたほうが「人に解りやすい」というメリットがあります。
 +
<syntaxhighlight lang="cpp">
 +
int a = 1'000; // 千
 +
long int b = 1'000'000; // 100万
 +
long long int c = 1'000'000'000; // 10億
 +
</syntaxhighlight>
 +
2進数や16進数も区切ると見やすくなります。
 +
<syntaxhighlight lang="cpp">
 +
uint16_t a = 0b11110000'00001111;
 +
uint32_t b = 0xff'00'ff'ff;
 +
</syntaxhighlight>
 +
 +
小数点を区切ることもできます。
 +
<syntaxhighlight lang="cpp">
 +
double pi = 3.14159'26535;
 +
</syntaxhighlight>
 +
 +
== 非推奨をマークする<nowiki>[[deprecated]]</nowiki> ==
 +
deprecated属性は、エンティティを非推奨扱いする属性です。
 +
「非推奨扱いの名前」が使用される場合、「警告メッセージ」を出せます。
 +
<syntaxhighlight lang="cpp">
 +
// 非推奨の関数
 +
[[deprecated]] char * gets(char *str);
 +
 +
// コメント
 +
[[deprecated("gets is deprecated."
 +
" Use gets_s instead.")]]
 +
</syntaxhighlight>
 +
 +
たとえば、「非推奨の関数」は、いきなり削除はできません。
 +
「現実的な解」として、「非推奨の関数」の実装を置き換えてしまうことが可能かもしれませんが、必ずしも置き換え可能ではありませんし、完全な形の置き換えができるかはわかりません。実装を変更することにより、互換性の問題が発生する可能性など、サイドエフェクトが考えられます。
 +
 +
「非推奨な関数」を利用しているかどうか、気付くのは難しく、[[C++コンパイラ]]で警告を出し、プログラマに撲滅していって貰うのが良いでしょう。
  
 
== ライブラリ ==
 
== ライブラリ ==
行147: 行221:
 
llvm-3.4-examples llvm-3.4-runtime cpp11-migrate-3.4 clang-format-3.4
 
llvm-3.4-examples llvm-3.4-runtime cpp11-migrate-3.4 clang-format-3.4
 
</syntaxhighlight>
 
</syntaxhighlight>
 
+
=== FreeBSD ===
 +
{{pkg|gcc49}}
 +
{{pkg|clang34}}
 
== 関連項目 ==
 
== 関連項目 ==
 
* [[C++14]]
 
* [[C++14]]
行155: 行231:
 
* [[exchange]]
 
* [[exchange]]
 
* [[auto]]
 
* [[auto]]
<!-- vim: filetype=mediawiki -->
+
<!-- vim: filetype=mediawiki
 +
-->

2014年4月6日 (日) 11:57時点における版

C++14 とは、C++11のマイナーバージョンアップとラムダ式などの機能追加を行われたバージョン版のC++です。

読み方

C++14
しーぷらすぷらす じゅうよん

概要

C++14では、C++98に対するC++03程度の修正を予定していたが、機能追加を行われることになりました。 2014年度中に仕様が策定される予定です。 C++14の後は、C++17を目指す C++1yが予定されています。

コア言語

  • 2進数リテラル
  • 実行時サイズの配列
  • 通常の関数の戻り値型の推論
  • ジェンリックラムダ
  • 一般化されたラムダキャプチャ
  • constexpr 関数の制限の緩和
  • 変数テンプレート
  • 軽量コンセプト

2進数リテラル

0b もしくは 0B のプレフィックスをつけて、数値の2進数リテラルを記述できます。

int i = 0b1100; // i = 12

実行時サイズの配列

配列のサイズ(要素数)を実行時の値で指定できるようになります。

void f(std::size_t size) {
	int a[size]; // 実行時サイズの配列
}

Cとは、sizeofで値がとれないなど、細かい部分で互換性がありません。

クラス内で使用できないケースがあります。 構造体内の動的配列は、 Variable Length Array In Structure(VLAIS) と呼ばれます。 C++14の実行時サイズ配列は、VLAISをサポートしません。

void f(std::size_t size) {
	struct {
		int a[size]; // GCC VLAIS, C++14 ではエラーになる
	} valis;
}

通常の関数の戻り値型の推論

ラムダ式と同様に、通常の関数でもreturn文から戻り値の型を推論できるようにします。

auto f();	// 関数宣言では、戻り値の型は、不明
auto f(){return 123;};	// 関数f()の定義で、戻り値の型は int となる。
int x = f();// x = 123;

return文のオペランドの式から推定されます。

K&R Cは、関数の戻り値型を省略した場合、暗黙にint型として扱われました。

f() { return 0.0; }	// K&R C, int

K&R Cの短絡的な型省略とC++14の型推論の違いは、C++14の戻り値の型推論機能は、関数本体のreturn文のオペランドの式を評価した結果の型であることです。

decltype(auto)

decltype(auto)は、戻り値型の推定に追加された機能です。

decltype(変数)で、変数の型と同じ型を指定できます。

auto a = 10;	// int a = 10; と同義
decltype(a) b;	// int b; と同義
std::vector<decltype<a> v;	// std::vector<int> v; と同義

ジェンリックラムダ

ラムダ式のパラメータがジェンリックにできるようになります。

[](const auto& a, const auto& b) {
	return a > b;
};

Varadic template parameter(パラメーターパック)も使用できます。

auto f = [](auto ... args) {};
f();
f(0);
f(0,1);
f(0,1,2,3,4,5);

一般化されたラムダキャプチャ

C++11では、非staticデータメンバーは、コピーキャプチャできませんでした。

int x = 1;
// xをコピーしたy, xの参照をキャプチャしたz
auto f = [y=x, &z=x] { ... };
 
auto g = [y = x + 1] { return y; }; // 2を返す

ムーブキャプチャ

std::unique_ptr<int> p(new int(3));
auto f = [p = std::move(p)]{ ...; };

constexpr 関数の制限の緩和

  • if, switch による条件分岐を許可
  • for, while, do-while のループの許可
  • void 戻り値型の許可
    • パラメータの参照で書き換えを行う
  • 初期化をともなう変数宣言の許可
    • static, thread_local は除く
  • 変数書き換えの許可
constexpr int abs(int i) {
	if (i < 0) {
		i = -i;
	}
	return i;
}

変数テンプレート

変数定義にテンプレートを使用できるようになります。

template <class T> constexpr T pi = T(3.1415);
 
template <class T>
T menseki(T hankei) {
	return pi<T> * hankei * hankei;
}

軽量コンセプト

  • コンセプトの軽量版
  • テンプレートの型制約機能

数値区切り

「数値区切り」とは、「数値リテラルを単一引用符で区切る」機能です。区切りの桁は、任意です。 大きな数字は、区切りを入れたほうが「人に解りやすい」というメリットがあります。

int	a = 1'000;		// 千
long int	b = 1'000'000;	// 100万
long long int	c = 1'000'000'000;	// 10億

2進数や16進数も区切ると見やすくなります。

uint16_t a = 0b11110000'00001111;
uint32_t b = 0xff'00'ff'ff;

小数点を区切ることもできます。

double pi = 3.14159'26535;

非推奨をマークする[[deprecated]]

deprecated属性は、エンティティを非推奨扱いする属性です。 「非推奨扱いの名前」が使用される場合、「警告メッセージ」を出せます。

// 非推奨の関数
[[deprecated]] char * gets(char *str);
 
// コメント
[[deprecated("gets is deprecated."
	" Use gets_s instead.")]]

たとえば、「非推奨の関数」は、いきなり削除はできません。 「現実的な解」として、「非推奨の関数」の実装を置き換えてしまうことが可能かもしれませんが、必ずしも置き換え可能ではありませんし、完全な形の置き換えができるかはわかりません。実装を変更することにより、互換性の問題が発生する可能性など、サイドエフェクトが考えられます。

「非推奨な関数」を利用しているかどうか、気付くのは難しく、C++コンパイラで警告を出し、プログラマに撲滅していって貰うのが良いでしょう。

ライブラリ

  • make_unique()
  • exchange()
  • コンパイル時 整数シーケンス
  • tupleの型指定 get()
  • quoted マニピュレータ
  • ユーザー定義リテラルライブラリ
  • Type Traits のエイリアステンプレート
  • optional 型
  • 実行サイズの配列
  • 共有 mutex
  • ファイルシステム
  • ネットワークライブラリ

GNU GCC/g++ C++14 サポート状況

  • http://gcc.gnu.org/projects/cxx1y.html
  • g++49(GCC 4.9)が比較的いろいろサポートしています。
    • Tweak to certain C++ contextual conversions N3323 4.9
    • Binary literals N3472 4.3 (GNU) , 4.9 (N3472)
    • Return type deduction for normal functions N3638 4.8 (N3386) , 4.9 (N3638)
    • (Moved from the standard to a separate technical specification) N3639 ?.? (GNU VLAs) , 4.9 (N3639)
    • Generalized lambda capture (init-capture) N3648 4.5 (partial) , 4.9 (N3648)
    • Generic (polymorphic) lambda expressions N3649 4.9
    • ((deprecated)) attribute N3760 4.9 (N3797)
    • Single-quotation-mark as a digit separator N3781 4.9 (N3797)
  • g++49 でサポートされていないもの。
    • Runtime-sized arrays with automatic storage duration
    • Variable templates N3651 No [WIP]
    • Relaxing requirements on constexpr functions N3652 No
    • Member initializers and aggregates N3653 No
    • Clarifying memory allocation N3664 N/A
    • Sized deallocation N3778 No

Clang clang++ C++14 サポート状況

  • http://clang.llvm.org/cxx_status.html
  • clang 3.4(clang++34)
    • clang 3.4 で C++14の機能を実装しました。
    • C++14は、clang++のオプション -std+c++1y で有効になります。

インストール

Ubuntu

sudo wget -O - http://llvm.org/apt/llvm-snapshot.gpg.key | sudo apt-key add -
sudo apt-get install clang-3.4 lldb-3.4
sudo add-apt-repository 'deb http://llvm.org/apt/precise/ llvm-toolchain-precise main'
wget -O - http://llvm.org/apt/llvm-snapshot.gpg.key|sudo apt-key add -
sudo apt-get update
sudo apt-get install clang-3.4 clang-3.4-doc libclang-common-3.4-dev \
libclang-3.4-dev libclang1-3.4 libclang1-3.4-dbg libllvm-3.4-ocaml-dev \
libllvm3.4 libllvm3.4-dbg lldb-3.4 llvm-3.4 llvm-3.4-dev llvm-3.4-doc \
llvm-3.4-examples llvm-3.4-runtime cpp11-migrate-3.4 clang-format-3.4

FreeBSD

sudo pkg install gcc49
sudo pkg install clang34

関連項目