SlideShare a Scribd company logo
2
Most read
7
Most read
8
Most read
templateとautoの型推論
2015/1/28 EMC1
光成滋生(@herumi)
このテキストでの記法
T : templateの型
ParamType : Tを含む複雑な型
ParamType = T, const T&, T*, ...
templateの型推論は3パターン
ParamTypeがポインタ型かuniversalでない参照型
universalな参照型
詳細はItem 24で(右辺値参照:以降univ参照と表記)
その他
Item 1 : templateの型推論
// 宣言
template<class T> void f(ParamType param);
// 呼び出し
f(expr);
2/22
exprが参照型なら参照部分を取り除く
ParamTypeにしたがってTを決める
ParamType = T&のときの例
constオブジェクトを関数に渡しても値は変わらないべき
ParamTypeがポインタかunivでない参照
template<class T> void f(T& param);
int x = 27;
const int cx = x;
const int& rx = x;
f(x); // T = int, param = int&
f(cx); // T = const int, param = const int&
f(rx); // T = const int, param = const int&
3/22
ParamType = const T&のときの例
rxの参照は無視されるのでx, cxと同じ
ParamTypeがポインタかunivでない参照
template<class T> void f(const T& param);
int x = 27;
const int cx = x;
const int& rx = x;
f(x); // T = int, param = const int&
f(cx); // T = int, param = const int&
f(rx); // T = int, param = const int&
4/22
ParamType = T*のときの例
参照とポインタは本質的に同じ
ParamTypeがポインタかunivでない参照
template<class T> void f(T* param);
int x = 27;
const int* px = &x;
f(&x); // T = int, param = int*
f(px); // T = const int, param = const int*
5/22
exprがrvalueなら一つ目と同じ規則
exprがlvalueならTとParamTypeはlvalue参照で
あるかのように推論される
Tが参照型になるのはこのときだけ
ParamTypeはrvalue参照であるかのように定義される
が型はlvalue参照になる
exprがlvalueかrvalueかによって違うのが重要
ParamTypeがuniversal参照
6/22
ParamType = T&&のときの例
参照とポインタは本質的に同じ
ParamTypeがuniversal参照
template<class T> void f(T&& param);
int x = 27;
const int cx = x;
const int& rx = x;
f(27); // rvalue : T = int, param = int&&
f(x); // lvalue : T = int&, param = int&
f(cx); // lvalue : T = const int&, param = const int&
f(rx); // lvalue : T = const int&, param = const int&
7/22
値渡しになる
paramはコピーされる
参照, const, volatileは無視される
ParamTypeがポインタでも参照でもない
template<class T> void f(T param);
int x = 27;
const int cx = x;
const int& rx = x;
f(x); // T = param = int
f(cx); // T = param = int
f(rx); // T = param = int
8/22
exprが差す先のconst性は無視されない
ParamTypeがポインタでも参照でもない
template<class T> void f(T param);
const char *const p = "abc";
f(p); // T = param = const char *
9/22
ポインタと配列は異なる型
大抵は配列は先頭要素へのポインタに変換される
関数パラメータには配列型がない
templateも同様
配列
const char name[] = "abc"; // const char[4]
const char *p = name; // const char*
void f(int *param);
void f(int param[]); // int *paramと同じ
template<class T> void f(T param);
f(name); // T = const char *
10/22
配列への参照は変換されない
配列のサイズを取得するテクニック
C++11ならarray<T, N>がある
注意:array<T,3>::iteratorとarray<T,5>::iteratorは同じ型かも
配列への参照
const char name[] = "abc"; // const char[4]
template<class T> void f(T& param);
f(name); // T = const char (&)[4]
template<class T, size_t N>
constexpr size_t arraySize(const T (&)[N]) noexcept {
return N;
}
11/22
関数型も関数ポインタに変換される
関数型への参照は変換されない
関数
void g(int);
template<class T>void f1(T param);
template<class T>void f2(T& param);
f1(g); // T = void (*)(int);
f2(g); // T = void (&)(int);
12/22
 template<class T> void f(Para para)の分類
 関数f(Para)にXを渡したときのTの型
\ 関数
\
渡す型X
f(T) f(T&) f(const T&) f(T&& para)
T=
para
T&
=para
const T&
=para
T para
int int int int int& int&
int& int int int int& int&
const int int const int int const
int&
const
int&
const
int&
int const int int const
int&
const
int&
1 int error int int int&&
一覧表
13/22
参照型の参照は無視される
universal参照はlvalueとrvalueでルールが異なる
値渡しではconst, volatileは無視される
arrayや関数は参照でないならポインタになる
Item 1のまとめ
14/22
autoの型推論は殆どtemplateの型推論と同じ
autoはParamTypeとして振る舞う
参照をつけないと値はコピーされる
Item 2 : autoの型推論
auto x = 27;
は
template<class T>
void f_for_x(T param);
f_for_x(27);
の挙動と等しい。
const auto& rx = x;
は
template<class T>
void f_for_rx(const T& param);
f_for_rx(x);
の挙動と等しい。
15/22
Item 1の分類に応じる
autoの推論例
auto x = 27; // int
const auto cx = x; // const int
const auto& rx = x; // const int&
auto&& ur1 = x; // xはintでlvalueなのでint&
auto&& ur2 = cx; // cxはconst intでlvalueなのでconst int&
auto&& ur3 = 27; // 27はintでrvalueなのでint&&
const char name[] = "abc";
auto a1 = name; // const char *
auto& a2 = name; // const char (&)[4];
void func(int, double);
auto f1 = func; // void (*)(int, double);
auto& f2 = func; // void (&)(int, double);
16/22
autoは一つの要素でも初期化リストになる
template関数に直接渡せない
初期化リストの注意点(1/2)
int x1(3); // x1 = 3
int x2{5}; // x2 = 5
auto a1(3); // int a1 = 3;
auto a2{5}; // std::initializer_list<int> a2 = {5};
template<class T> void f(T param);
auto a{1, 2, 3};
f(a); // ok
f({1, 2, 3}); // なぜかerror
template<class T> void f(std::initializer_list<T> param);
f({1, 2, 3}); // これはok
17/22
C++17から変わる(N3922)
auto x = {1}; // 初期化リスト
auto x = {2, 3, 4}; // 初期化リスト
auto x{1}; // int
auto x{2, 3, 4}; // エラー
autoがtemplate型の推論型になるところ
ラムダ関数のauto引数
C++14のreturnのauto
クイズ これは?
初期化リストの注意点(2/2)
auto f() {
return {1, 2}; // error
}
const auto x{2, 3, 4};
auto f = [&](auto x) { return x.size(); }
f(x); // ok
f({1, 2}); // error
18/22
auto x{0xf, 0xffffffff};
auto y{4294967295, 0xffffffff};
C++17から変わる(N3922)
const auto x = {1}; // 初期化リスト
const auto x = {2, 3, 4}; // 初期化リスト
const auto x{1}; // int
const auto x{2, 3, 4}; // エラー
autoを使うと無駄なコピーが発生するかも
std::vector<int> v = vs[i]; とコピー
forとautoの組み合わせの注意点(1/4)
std::vector<std::vector<int>> vs;
for (auto v : vs) { ... }
std::vector<std::vector<int>> vs;
for (auto& v : vs) { ... } // 値を変更するとき
for (const auto& v : vs { ... } // 値をいじらないとき
19/22
std::vector<bool>に対してauto&はエラー
vector<bool>は一時オブジェクトを生成するため
auto&&を使う
auto&&は先程の例でもうまくいく
いつでもauto&&でええんじゃないか
auto&&を省略してしまってもいいんじゃないか
規格に提案されclang/VCで実装されたが却下される
forとautoの組み合わせの注意点(2/4)
std::vector<bool> v;
for (auto& e : v) // エラー
for (auto&& e : v) // うまくいく
20/22
const auto&よりautoがよいレアケース
forとautoの組み合わせの注意点(3/4)
void fff(int *y, std::array<int, 2>& v) {
for (const auto& x : v) {
*y += x;
*y += x;
}
}
movl (%rdi), %eax ; eax ← y
addl (%rsi), %eax ; eax ← v[0]
movl %eax, (%rdi) ; yを更新
addl (%rsi), %eax ; eax ← v[0] もう一度値を読む
movl %eax, (%rdi)
addl 4(%rsi), %eax ; eax ← v[1]
movl %eax, (%rdi)
addl 4(%rsi), %eax ; eax ← v[1] もう一度読む
movl %eax, (%rdi)
retq
21/22
yの更新でxが変わる可能性を考慮するため
autoにして値は変わらないとコンパイラに教える
注意 : この場合はyの一時変数を導入するのが一番よい
forとautoの組み合わせの注意点(4/4)
void fff(int *y, std::array<int, 2>& v) {
for (auto x : v) {
*y += x;
*y += x;
} }
movl (%rsi), %eax ; eax ← v[0]
addl %eax, %eax ; eaxを2倍して
addl (%rdi), %eax ; yを足す
movl %eax, (%rdi) ; yに書き戻す
movl 4(%rsi), %ecx ; ecx ← v[1]
leal (%rax,%rcx,2), %eax ; ecxの2倍を足す
movl %eax, (%rdi)
retq
22/22

More Related Content

PDF
Effective Modern C++ 勉強会#3 Item16
PPTX
Emcpp0506
PDF
Effective Modern C++ 勉強会#1 Item3,4
PDF
ゲーム開発者のための C++11/C++14
PPTX
Effective Modern C++ Item 9 and 10
PDF
emc++ chapter32
PDF
CUDAのアセンブリ言語基礎のまとめ PTXとSASSの概説
PDF
中3女子でもわかる constexpr
Effective Modern C++ 勉強会#3 Item16
Emcpp0506
Effective Modern C++ 勉強会#1 Item3,4
ゲーム開発者のための C++11/C++14
Effective Modern C++ Item 9 and 10
emc++ chapter32
CUDAのアセンブリ言語基礎のまとめ PTXとSASSの概説
中3女子でもわかる constexpr

What's hot (20)

PDF
組み込みでこそC++を使う10の理由
PDF
C++ マルチスレッドプログラミング
PPTX
Effective Modern C++ 勉強会 Item 22
PDF
中3女子が狂える本当に気持ちのいい constexpr
PDF
すごい constexpr たのしくレイトレ!
PPTX
C# 8.0 null許容参照型
PDF
2015年度GPGPU実践プログラミング 第7回 総和計算
PPTX
Effective Modern C++勉強会#4 Item 17, 18資料
PDF
オブジェクト指向できていますか?
PDF
Effective Modern C++ 勉強会#7 Item 27
PDF
規格書で読むC++11のスレッド
PPTX
C#や.NET Frameworkがやっていること
PDF
CuPy解説
PDF
C++ マルチスレッド 入門
PDF
関数型プログラミングのデザインパターンひとめぐり
PDF
マルチコアを用いた画像処理
PDF
関数型プログラミング入門 with OCaml
PPTX
Unityで使える C# 6.0~と .NET 4.6
PPTX
C#とILとネイティブと
PDF
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
組み込みでこそC++を使う10の理由
C++ マルチスレッドプログラミング
Effective Modern C++ 勉強会 Item 22
中3女子が狂える本当に気持ちのいい constexpr
すごい constexpr たのしくレイトレ!
C# 8.0 null許容参照型
2015年度GPGPU実践プログラミング 第7回 総和計算
Effective Modern C++勉強会#4 Item 17, 18資料
オブジェクト指向できていますか?
Effective Modern C++ 勉強会#7 Item 27
規格書で読むC++11のスレッド
C#や.NET Frameworkがやっていること
CuPy解説
C++ マルチスレッド 入門
関数型プログラミングのデザインパターンひとめぐり
マルチコアを用いた画像処理
関数型プログラミング入門 with OCaml
Unityで使える C# 6.0~と .NET 4.6
C#とILとネイティブと
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
Ad

Similar to templateとautoの型推論 (20)

PDF
C++コミュニティーの中心でC++をDISる
PDF
What is template
PDF
C++0x 言語の未来を語る
PDF
テンプレートメタプログラミング as 式
PDF
C++ Template Meta Programming の紹介@社内勉強会
PPTX
boost - std - C#
PDF
Iterators must-go(ja)
PPTX
2016年第二回プレ卒研in山口研
PDF
C++ Template Metaprogramming
PDF
Template Meta Programming入門から応用まで
PPTX
C++14言語編
PDF
Boost Tour 1_58_0 merge
PDF
C++14 Overview
PDF
C++0x in programming competition
PDF
C++勉強会in広島プレゼン資料
PDF
わんくま同盟大阪勉強会#61
PDF
リテラル文字列型までの道
PDF
C++11のつかいかた
PPTX
Visual C++で使えるC++11
C++コミュニティーの中心でC++をDISる
What is template
C++0x 言語の未来を語る
テンプレートメタプログラミング as 式
C++ Template Meta Programming の紹介@社内勉強会
boost - std - C#
Iterators must-go(ja)
2016年第二回プレ卒研in山口研
C++ Template Metaprogramming
Template Meta Programming入門から応用まで
C++14言語編
Boost Tour 1_58_0 merge
C++14 Overview
C++0x in programming competition
C++勉強会in広島プレゼン資料
わんくま同盟大阪勉強会#61
リテラル文字列型までの道
C++11のつかいかた
Visual C++で使えるC++11
Ad

More from MITSUNARI Shigeo (20)

PDF
暗号技術の実装と数学
PDF
範囲証明つき準同型暗号とその対話的プロトコル
PDF
暗認本読書会13 advanced
PDF
暗認本読書会12
PDF
暗認本読書会11
PDF
暗認本読書会10
PDF
暗認本読書会9
PDF
Intel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgen
PDF
暗認本読書会8
PDF
暗認本読書会7
PDF
暗認本読書会6
PDF
暗認本読書会5
PDF
暗認本読書会4
PDF
深層学習フレームワークにおけるIntel CPU/富岳向け最適化法
PDF
私とOSSの25年
PDF
WebAssembly向け多倍長演算の実装
PDF
Lifted-ElGamal暗号を用いた任意関数演算の二者間秘密計算プロトコルのmaliciousモデルにおける効率化
PDF
楕円曲線と暗号
PDF
HPC Phys-20201203
PDF
BLS署名の実装とその応用
暗号技術の実装と数学
範囲証明つき準同型暗号とその対話的プロトコル
暗認本読書会13 advanced
暗認本読書会12
暗認本読書会11
暗認本読書会10
暗認本読書会9
Intel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgen
暗認本読書会8
暗認本読書会7
暗認本読書会6
暗認本読書会5
暗認本読書会4
深層学習フレームワークにおけるIntel CPU/富岳向け最適化法
私とOSSの25年
WebAssembly向け多倍長演算の実装
Lifted-ElGamal暗号を用いた任意関数演算の二者間秘密計算プロトコルのmaliciousモデルにおける効率化
楕円曲線と暗号
HPC Phys-20201203
BLS署名の実装とその応用

templateとautoの型推論