More Related Content
Similar to Lambda in template_final
Similar to Lambda in template_final (20)
Lambda in template_final
- 8. 答え (ラムダ式の出現に制限がな
いとき):
template<class T, class... Args>
constexpr decltype([] {
T t(create<Args>()...);
}, true)
test(int)
{ return true; }
template<class T>
constexpr bool test(bool)
{ return false; }
8
- 21. マングリングの例
void f(int)
{
.....
}
$ g++ -std=c++ -c main.cpp
$ nm main.o
0000000000000009 T _Z1fd
0000000000000000 T _Z1fi
void f(double) $ c++filt _Z1fi
{
f(int)
.....
$ c++filt _Z1fd
}
f(double)
21
- 25. マングリングの例
$ g++ -std=c++11 -c a.cpp
// a.cpp
void f(int) $ nm a.o
0000000000000000 T _Z1fi
{
$ c++filt _Z1fi
.....
f(int)
}
// b.cpp
int f(int)
{
.....
}
$ g++ -std=c++11 -c a.cpp
$ nm a.o
0000000000000000 T _Z1fi
$ c++filt _Z1fi
f(int)
25
- 26. マングリングの例
$ g++ -std=c++11 -c a.cpp
// a.cpp
void f(int) $ nm a.o
0000000000000000 T a.o b.o
$ g++ -std=c++11 -c _Z1fi
{
$ c++filt _Z1fi
.....
(リンク時に定義の異なる関数に対す
f(int)
}
るシンボルが衝突するので何が起きる
か分からない)
$ g++ -std=c++11 -c a.cpp
// b.cpp
が,元々 well-defined なプログラム
$ nm a.o
int f(int) じゃないのでそんなことは知ったこっ
0000000000000000 T _Z1fi
{
ちゃない!
$ c++filt _Z1fi
.....
f(int)
}
26
- 31. template<typename T>
auto add(T const &x, T const &y)
関数テンプレートの特殊化
-> decltype(x + y)
{に対するマングリングの例
return x + y; }
struct X
{
X operator+(X const &rhs) const
{ ..... }
};
int main()
{
X x, y;
add(x, y);
}
31
- 32. template<typename T>
auto add(T const &x, T const &y)
関数テンプレートの特殊化
-> decltype(x + y)
{に対するマングリングの例
return x + y; }
struct X
{
X g++ -std=c++11const &rhs) const
$ operator+(X -c main.cpp
{ nm main.o
$ ..... }
}; 0000000000000000 W _Z3addI1XEDTplfp_fp0_ERKT_S4_
int main()
{
X x, y;
add(x, y);
}
32
- 33. template<typename T>
auto add(T const &x, T const &y)
関数テンプレートの特殊化
-> decltype(x + y)
{に対するマングリングの例
return x + y; }
struct X
{
X g++ -std=c++11const &rhs) const
$ operator+(X -c main.cpp
{ nm main.o
$ ..... }
}; 0000000000000000 W _Z3addI1XEDTplfp_fp0_ERKT_S4_
$ c++filt _Z3addI1XEDTplfp_fp0_ERKT_S4_
int main()
{
X x, y;
add(x, y);
}
33
- 34. template<typename T>
auto add(T const &x, T const &y)
関数テンプレートの特殊化
-> decltype(x + y)
{に対するマングリングの例
return x + y; }
struct X
{
X g++ -std=c++11const &rhs) const
$ operator+(X -c main.cpp
{ nm main.o
$ ..... }
}; 0000000000000000 W _Z3addI1XEDTplfp_fp0_ERKT_S4_
$ c++filt _Z3addI1XEDTplfp_fp0_ERKT_S4_
decltype
int main()({parm#1}+{parm#2}) add<X>(X const&, X
const&)
{
X x, y;
add(x, y);
}
34
- 43. 式をそのままマングリングって
なんなの? 馬鹿なの? 死ぬ
の?
decltype ({parm#1}+{parm#2}) add<X>(X const&, X const&)
1つ目のパラメタが X const の左辺値だと
特殊化の時点で分かる
2つ目のパラメタが X const の左辺値だと
特殊化の時点で分かる
ゆえにX constの左辺値とX constの左辺値との
operator+の戻り値型も特殊化の時点で分かる
43
- 44. 式をそのままマングリングって
なんなの? 馬鹿なの? 死ぬ
の?
decltype ({parm#1}+{parm#2}) add<X>(X const&, X const&)
疑問:
1つ目のパラメタが X const の左辺値だと
特殊化の時点で分かる
add<X>(X const&, X const&) を
X
マングリングすればええやん???
2つ目のパラメタが X const の左辺値だと
特殊化の時点で分かる
戻り値の型やパラメタ型に現れる
ゆえにX constの左辺値とX constの左辺値との
定数式や型の計算を全部やった結果を
operator+の戻り値型も特殊化の時点で分かる
マングリングすればええやん???
44
- 54. // generic_add.hpp
T に operator+ が宣言されている
場合のバージョン
思い出そう:マングリング
template<typename T>
は
auto generic_add(T const &x, T const
&y)
-> decltype(x + y)
{
}
return x + y;T に非メンバ関数 add が
宣言されている場合のバージョン
template<typename T>
auto generic_add(T const &x, T const &y)
-> decltype(add(x, y))
{
return add(x, y);
}
54
- 55. // generic_add.hpp
T に operator+ が宣言されている
場合のバージョン
思い出そう:マングリング
template<typename T>
は
auto generic_add(T const &x, T const
&y)
-> decltype(x + y)
{
}
return x + y;T に非メンバ関数 add が
宣言されている場合のバージョン
template<typename T>
auto generic_add(T const &x, T const &y)
異なる関数テンプレート定義からインスタンス
-> decltype(add(x, y))
{ 化された特殊化は,たとえ名前,テンプレート
引数,戻り値の型,パラメタの型のすべてが同
return add(x, y);
じであっても共存できる
}
55
- 56. // x.hpp
Struct X .....
// a.cpp
#include <x.hpp>
#include <generic_add.hpp>
// b.cpp
#include <x.hpp>
#include <generic_add.hpp>
X operator+(X const &x,
X const &y)
{
.....
}
X add(X const &x,
X const &y)
{
.....
}
void f()
{
X x;
X y;
generic_add(x, y);
}
void g()
{
X x;
X y;
generic_add(x, y);
}
56
- 57. // x.hpp
Struct X .....
// a.cpp
#include <x.hpp>
#include <generic_add.hpp>
// b.cpp
#include <x.hpp>
#include <generic_add.hpp>
X add(X const &x,
X operator+(X const &x,
X const &y)
X const &y)
{
{ 異なる関数テンプレート定義をインスタンス化
.....
.....
特殊化が共存可能
}
}
void f()
{
X x;
X y;
generic_add(x, y);
}
void g()
{
X x;
X y;
generic_add(x, y);
}
57
- 58. // x.hpp
struct X .....
// a.cpp
#include <x.hpp>
#include <generic_add.hpp>
// b.cpp
#include <x.hpp>
#include <generic_add.hpp>
X add(X const &x,
X operator+(X const &x,
_Z11generic_addI1XET_RKS1_S3_
X const &y)
X const &y)
{
異なる関数テンプレート定義をインスタンス化
{ decltype ({parm#1}+{parm#2})
.....
.....
generic_add<X>(X const&, X const&)
特殊化が共存可能
}
}
void f()
{
X x;
X y;
generic_add(x, y);
}
void g()
{
X x;
X y;
generic_add(x, y);
}
58
- 59. // x.hpp
struct X .....
// a.cpp
#include <x.hpp>
#include <generic_add.hpp>
// b.cpp
#include <x.hpp>
#include <generic_add.hpp>
X add(X const &x,
X operator+(X const &x,
_Z11generic_addI1XET_RKS1_S3_
X const &y)
X const &y)
{
異なる関数テンプレート定義をインスタンス化
{ decltype ({parm#1}+{parm#2})
.....
.....
generic_add<X>(X const&, X const&)
特殊化が共存可能
}
}
_Z11generic_addI1XEDTcl3addfp_fp0_EERKT_S4_
void g()
void f()
{
{ decltype (add({parm#1}, {parm#2}))
X x;
generic_add<X>(X const&, X const&)
X x;
X y;
X y;
generic_add(x, y);
generic_add(x, y);
}
}
59
- 60. // x.hpp
struct X .....
// a.cpp
#include <x.hpp>
#include <generic_add.hpp>
// b.cpp
#include <x.hpp>
#include <generic_add.hpp>
X add(X const &x,
X operator+(X const &x,
_Z11generic_addI1XET_RKS1_S3_
X const &y)
X const &y)
{
異なる関数テンプレート定義をインスタンス化
{ decltype ({parm#1}+{parm#2})
.....
.....
generic_add<X>(X const&, X const&)
特殊化が共存可能
}
}
_Z11generic_addI1XEDTcl3addfp_fp0_EERKT_S4_
void g()
void f()
{
{ decltype (add({parm#1}, {parm#2}))
X x;
generic_add<X>(X const&, X const&)
X x;
X y;
X y;
generic_add(x, y);
generic_add(x, y);
この2つの翻訳単位をリンクしても問題なし
}
}
60
- 62. 捕捉:実際に GCC が従っている
ABI はあらゆる式に対するマング
リング規則を定めている
http://mentorembedded.github.
io/cxx-abi/abi.html#mangling
62