├── src ├── item7-1.cpp ├── item26-2.cpp ├── item14-1.cpp ├── item20-2.cpp ├── item21-5.cpp ├── item7-3.cpp ├── item20-1.cpp ├── item21-4.cpp ├── item18.cpp ├── item21-2.cpp ├── item12-1.cpp ├── item6-1.cpp ├── item21-1.cpp └── item21-3.cpp ├── misc └── mail.md ├── readme.md └── memo.md /src/item7-1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct W { 4 | W(int, bool){} 5 | W(int, double){} 6 | W(std::initializer_list){} 7 | }; 8 | 9 | int main() 10 | { 11 | W w{10, 5.0}; // error 12 | } 13 | 14 | -------------------------------------------------------------------------------- /src/item26-2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | struct B { 6 | template::type>::value>::type> 7 | explicit B(T&& s) 8 | : s(std::forward(s)) 9 | { 10 | puts("forward"); 11 | } 12 | B(int) { puts("int"); } 13 | B(short) { puts("short"); } 14 | std::string s; 15 | }; 16 | 17 | int main() 18 | { 19 | B b1("abc"); 20 | B b2(3); 21 | short i = 4; 22 | B b3(i); 23 | B b4(b1); 24 | } -------------------------------------------------------------------------------- /src/item14-1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct A { 5 | A() { puts("cstr"); } 6 | ~A() { puts("dstr"); } 7 | }; 8 | 9 | void f_noexcept() noexcept { 10 | A a; 11 | throw 1; 12 | } 13 | 14 | void f_nothrow() throw() { 15 | A a; 16 | throw 1; 17 | } 18 | 19 | void putmsg() 20 | { 21 | puts("putmsg is called"); 22 | } 23 | 24 | int main() 25 | { 26 | std::set_unexpected(putmsg); 27 | #ifdef NOEXCEPT 28 | puts("noexcept"); 29 | f_noexcept(); 30 | #else 31 | puts("throw()"); 32 | f_nothrow(); 33 | #endif 34 | } -------------------------------------------------------------------------------- /src/item20-2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct A { 5 | A() { puts("A cstr"); } 6 | ~A() { puts("A dstr"); } 7 | std::shared_ptr p; 8 | }; 9 | 10 | struct B { 11 | B() { puts("B cstr"); } 12 | ~B() { puts("B dstr"); } 13 | std::weak_ptr p; 14 | }; 15 | 16 | int main() 17 | { 18 | // leak 19 | { 20 | auto s = std::make_shared(); 21 | auto t = std::make_shared(); 22 | s->p = t; 23 | t->p = s; 24 | } 25 | // not leak 26 | { 27 | auto s = std::make_shared(); 28 | auto t = std::make_shared(); 29 | s->p = t; 30 | t->p = s; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/item21-5.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | struct A { 6 | int x[4]; 7 | static inline void* operator new(size_t size) 8 | { 9 | printf("new size=%d\n", (int)size); 10 | return malloc(size); 11 | } 12 | static inline void operator delete(void* p) 13 | { 14 | printf("free\n"); 15 | free(p); 16 | } 17 | }; 18 | 19 | int main() 20 | { 21 | { 22 | puts("new"); 23 | A *p = new A(); 24 | delete p; 25 | } 26 | { 27 | puts("shared_ptr"); 28 | auto p = std::shared_ptr(new A()); 29 | } 30 | { 31 | puts("make_shared"); 32 | auto p = std::make_shared(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/item7-3.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | template 5 | void func1(Ts&&... params) { 6 | T v(std::forward(params)...); 7 | for (auto x : v) { 8 | printf("%d\n", x); 9 | } 10 | } 11 | 12 | template 13 | void func2(Ts&&... params) { 14 | T v{std::forward(params)...}; 15 | for (auto x : v) { 16 | printf("%d\n", x); 17 | } 18 | } 19 | 20 | int main() 21 | { 22 | using Vec = std::vector; 23 | puts("A"); 24 | func1(10, 1); // 10 elements of 1 25 | puts("B"); 26 | func2(10, 1); // two elements of 10, 1 27 | } -------------------------------------------------------------------------------- /src/item20-1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct A { 5 | int a; 6 | A(int a) : a(a) { puts("cstr"); } 7 | ~A() { puts("dstr"); } 8 | void put() const { printf("a=%d\n", a); } 9 | }; 10 | 11 | void testAndPut(const std::weak_ptr& w) 12 | { 13 | puts("testAndPut"); 14 | if (auto p = w.lock()) { 15 | p->put(); 16 | } else { 17 | puts("none"); 18 | } 19 | } 20 | 21 | int main() 22 | { 23 | auto s = std::make_shared(3); 24 | s->put(); 25 | std::weak_ptr w = s; 26 | testAndPut(w); 27 | puts("s.reset()"); 28 | s.reset(); 29 | testAndPut(w); 30 | puts("s.reset(new A(5))"); 31 | s.reset(new A(5)); 32 | testAndPut(w); 33 | w = s; 34 | testAndPut(w); 35 | } 36 | -------------------------------------------------------------------------------- /src/item21-4.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | template 6 | std::unique_ptr make_unique(Args&&... args) { 7 | return std::unique_ptr(new T(std::forward(args)...)); 8 | } 9 | 10 | template 11 | void put(const T& v) 12 | { 13 | std::cout << "size=" << v.size(); 14 | for (const auto& x : v) { 15 | std::cout << ", " << x; 16 | } 17 | std::cout << std::endl; 18 | } 19 | 20 | using Vec = std::vector; 21 | 22 | int main() 23 | { 24 | auto pv1 = make_unique(10, 20); 25 | put(*pv1); 26 | // auto pv2 = make_unique({10, 20}); // error 27 | auto il = {10, 20}; 28 | auto pv3 = make_unique(il); // error 29 | put(*pv3); 30 | } 31 | -------------------------------------------------------------------------------- /src/item18.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct A { 5 | A() { puts("A cstr"); } 6 | virtual ~A() { puts("A dstr"); } 7 | }; 8 | 9 | struct B : A { 10 | B() { puts("B cstr"); } 11 | ~B() { puts("B dstr"); } 12 | }; 13 | 14 | auto delA0 = [](A* p) { 15 | printf("delA0 %p\n", p); 16 | delete p; 17 | }; 18 | 19 | void delA1(A* p) 20 | { 21 | printf("delA1 %p\n", p); 22 | delete p; 23 | } 24 | 25 | int main() 26 | { 27 | std::unique_ptr p(new A(), delA0); 28 | std::unique_ptr q(nullptr, delA0); 29 | q.reset(new B()); 30 | printf("sizeof p=%d\n", (int)sizeof(p)); // 8 31 | std::unique_ptr r(new A(), delA1); 32 | printf("sizeof r=%d\n", (int)sizeof(r)); // 16 33 | } 34 | -------------------------------------------------------------------------------- /src/item21-2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | struct A { 6 | A() { puts("A cstr"); } 7 | ~A() { puts("A dstr"); } 8 | }; 9 | 10 | struct B { 11 | B() { puts("B cstr"); throw std::bad_alloc(); } 12 | ~B() { puts("B dstr"); } 13 | }; 14 | 15 | struct C { 16 | C() : a(new A()) , b(new B()) { } 17 | ~C() 18 | { 19 | delete a; 20 | delete b; 21 | } 22 | A *a; 23 | B *b; 24 | }; 25 | 26 | #ifdef USE_MAKE_UNIQUE 27 | 28 | struct D { 29 | D() : a(new A()) , b(new B()) { } 30 | std::unique_ptr a; 31 | std::unique_ptr b; 32 | }; 33 | #endif 34 | 35 | int main() 36 | try 37 | { 38 | #ifdef USE_MAKE_UNIQUE 39 | D d; 40 | #else 41 | C c; 42 | #endif 43 | } catch (std::exception& e) { 44 | printf("ERR %s\n", e.what()); 45 | } 46 | -------------------------------------------------------------------------------- /src/item12-1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct X { 4 | X(){} 5 | void f() & { puts("1 f &"); } 6 | void f() && { puts("2 f &&"); } 7 | void f() const & { puts("3 f c&"); } 8 | void f() const && { puts("4 f c&&"); } 9 | void f() volatile & { puts("5 f v&"); } 10 | void f() volatile && { puts("6 f v&&"); } 11 | void f() const volatile & { puts("7 f cv&"); } 12 | void f() const volatile && { puts("8 f cv&&"); } 13 | }; 14 | 15 | int main() 16 | { 17 | X x; 18 | const X cx; 19 | volatile X vx; 20 | const volatile X cvx; 21 | x.f(); 22 | X().f(); 23 | cx.f(); 24 | static_cast(X()).f(); 25 | vx.f(); 26 | static_cast(X()).f(); 27 | cvx.f(); 28 | static_cast(X()).f(); 29 | } 30 | /* 31 | 1 f & 32 | 2 f && 33 | 3 f c& 34 | 4 f c&& 35 | 5 f v& 36 | 6 f v&& 37 | 7 f cv& 38 | 8 f cv&& 39 | */ 40 | -------------------------------------------------------------------------------- /src/item6-1.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Item 6. bad use of auto 3 | */ 4 | #include 5 | #include 6 | 7 | struct Ref { 8 | int& x; 9 | Ref(int& x) : x(x) { puts("Ref cstr"); } 10 | ~Ref() { puts("Ref dstr"); } 11 | operator int() { puts("read x"); return x; } 12 | }; 13 | 14 | struct Vec { 15 | int x; 16 | Vec() : x(5) { puts("Vec cstr"); } 17 | ~Vec() { puts("Vec dstr"); } 18 | Ref get() { return Ref(x); } 19 | }; 20 | 21 | Vec createVec() { return Vec(); } 22 | 23 | /* 24 | use int 25 | Vec cstr 26 | Ref cstr 27 | read x 28 | Ref dstr 29 | Vec dstr 30 | type=int a=5 31 | 32 | use auto 33 | Vec cstr 34 | Ref cstr 35 | Vec dstr 36 | read x 37 | type=struct Ref a=5 38 | Ref dstr 39 | */ 40 | int main() 41 | { 42 | puts("use int"); 43 | { 44 | int a = createVec().get(); 45 | printf("type=%s a=%d\n", typeid(a).name(), a); 46 | } 47 | puts(""); 48 | puts("use auto"); 49 | { 50 | auto a = createVec().get(); 51 | // access after calling destructor of Vec 52 | printf("type=%s a=%d\n", typeid(a).name(), (int)a); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/item21-1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | namespace std { 7 | template struct _Unique_if { 8 | typedef unique_ptr _Single_object; 9 | }; 10 | 11 | template struct _Unique_if { 12 | typedef unique_ptr _Unknown_bound; 13 | }; 14 | 15 | template struct _Unique_if { 16 | typedef void _Known_bound; 17 | }; 18 | 19 | template 20 | typename _Unique_if::_Single_object 21 | make_unique(Args&&... args) { 22 | return unique_ptr(new T(std::forward(args)...)); 23 | } 24 | 25 | template 26 | typename _Unique_if::_Unknown_bound 27 | make_unique(size_t n) { 28 | typedef typename remove_extent::type U; 29 | return unique_ptr(new U[n]()); 30 | } 31 | 32 | template 33 | typename _Unique_if::_Known_bound 34 | make_unique(Args&&...) = delete; 35 | } 36 | 37 | #include 38 | #include 39 | using namespace std; 40 | 41 | int main() { 42 | cout << *make_unique() << endl; 43 | cout << *make_unique(1729) << endl; 44 | cout << "\"" << *make_unique() << "\"" << endl; 45 | cout << "\"" << *make_unique("meow") << "\"" << endl; 46 | cout << "\"" << *make_unique(6, 'z') << "\"" << endl; 47 | 48 | auto up = make_unique(5); 49 | 50 | for (int i = 0; i < 5; ++i) { 51 | cout << up[i] << " "; 52 | } 53 | 54 | cout << endl; 55 | 56 | #if defined(ERROR1) 57 | auto up1 = make_unique("error"); 58 | #elif defined(ERROR2) 59 | auto up2 = make_unique(10, 20, 30, 40); 60 | #elif defined(ERROR3) 61 | auto up3 = make_unique(); 62 | #elif defined(ERROR4) 63 | auto up4 = make_unique(11, 22, 33, 44, 55); 64 | #endif 65 | } 66 | -------------------------------------------------------------------------------- /src/item21-3.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | cl item21-3.cpp /MT 3 | 4 | /DUSE_MAKE_SHARED 5 | 0 40 0 40 6 | 1 5781 1 5781 7 | 2 552 2 552 8 | 3 29 3 29 9 | 4 4096 4 4096 10 | 5 16 ; 5 32 ; 11 | 6 24 ; 6 32 ; 12 | 7 16 ; 7 32 ; 13 | 8 24 ; 14 | 9 16 ; 15 | 10 24 ; 16 | 17 | gcc 18 | 19 | 0 16 ; 0 40 20 | 1 24 ; 1 40 21 | 2 16 ; 2 40 22 | 3 24 23 | 4 16 24 | 5 24 25 | */ 26 | #include 27 | #include 28 | #include 29 | 30 | static int pos = 0; 31 | static struct Mmem { 32 | char buf[8192]; 33 | size_t size; 34 | } mem[4096]; 35 | 36 | void* operator new(size_t n) 37 | { 38 | if (n >= 8192) { 39 | puts("ERR"); 40 | exit(1); 41 | } 42 | mem[pos].size = n; 43 | printf("new %p %d\n", mem[pos].buf, (int)n); 44 | return mem[pos++].buf; 45 | } 46 | void operator delete(void *p) 47 | { 48 | if (p == 0) return; 49 | printf("delete %p\n", p); 50 | } 51 | 52 | struct A { 53 | int a[4]; 54 | }; 55 | 56 | void f() 57 | { 58 | #ifdef USE_MAKE_SHARED 59 | auto p = std::make_shared(); 60 | #else 61 | std::shared_ptr p(new A()); 62 | #endif 63 | printf("p=%p\n", &*p); 64 | } 65 | 66 | #ifdef USE_MAKE_UNIQUE 67 | template 68 | std::unique_ptr make_unique(Args&&... args) { 69 | return std::unique_ptr(new T(std::forward(args)...)); 70 | } 71 | #endif 72 | 73 | void g() 74 | { 75 | #ifdef USE_MAKE_UNIQUE 76 | auto p = make_unique(); 77 | #else 78 | std::unique_ptr p(new A()); 79 | #endif 80 | } 81 | 82 | struct L { 83 | int a[1024]; 84 | }; 85 | 86 | void lifetimeMain(std::shared_ptr p) 87 | { 88 | puts("new by shared_ptr"); 89 | printf("use_count=%d\n", (int)p.use_count()); 90 | std::weak_ptr w1; 91 | std::weak_ptr w2; 92 | { 93 | puts("shared q"); 94 | auto q = std::move(p); 95 | puts("ref by weak"); 96 | w1 = q; 97 | w2 = q; 98 | puts("reset q"); 99 | q.reset(); 100 | puts("reset weak"); 101 | w1.reset(); 102 | w2.reset(); 103 | puts("end of q"); 104 | } 105 | puts("shared end"); 106 | } 107 | 108 | void lifetimeShared() 109 | { 110 | puts("----------------"); 111 | puts("new by shared_ptr"); 112 | auto p = std::shared_ptr(new L()); 113 | lifetimeMain(std::move(p)); 114 | } 115 | 116 | void lifetimeMake() 117 | { 118 | puts("----------------"); 119 | puts("new by make_shared"); 120 | auto p = std::make_shared(); 121 | lifetimeMain(std::move(p)); 122 | } 123 | 124 | int main() 125 | { 126 | for (int i = 0; i < 3; i++) { 127 | f(); 128 | } 129 | for (int i = 0; i < 3; i++) { 130 | g(); 131 | } 132 | lifetimeShared(); 133 | lifetimeMake(); 134 | } 135 | -------------------------------------------------------------------------------- /misc/mail.md: -------------------------------------------------------------------------------- 1 | #### 結果 2 | 勉強会の中で出席者より質問のあった↑件、Scottに問い合わせ、本の内容に誤りがあったとの回答を得ました。errataにも掲載されました。 3 | 4 | http://www.aristeia.com/BookErrata/emc++-errata.html 5 | ! 1/30/15 txk PDF 12 6 | The third paragraph (beginning with "These examples all show lvalue reference parameters, but type deduction works exactly the same way for rvalue reference parameters") should be removed. When the type of param in the template f on page 11 is changed to an rvalue reference (i.e., to have type "T&&"), it becomes a universal reference, and then the rules for Case 2 (on pages 13-14) apply. 7 | 8 | #### 経緯 9 | Scottからメール掲載許可を得たので、今後の参考のためにもここに転載しておきます。 10 | 11 | ##### 私→Scott 12 | 13 | ``` 14 | Hi Soctt, 15 | 16 | This question is about 2015-01-20: Third Release. 17 | 18 | Item1 page 12, there is the following paragraph: 19 | ----- 20 | These examples all show lvalue reference parameters, but type deduction works 21 | exactly the same way for rvalue reference parameters. Of course, only 22 | rvalue arguments 23 | may be passed to rvalue reference parameters, but that restriction has nothing 24 | to do with type deduction. 25 | ----- 26 | 27 | That doesn't make sense for me. 28 | My first question is what these examples are. I think the examples are 29 | written in the previous page, page 11: 30 | 31 | template 32 | void f(T& param); // param is a reference 33 | 34 | int x = 27; // x is an int 35 | const int cx = x; // cx is a const int 36 | const int& rx = x; // rx is a reference to x as a const int 37 | 38 | f(x); // T is int, param's type is int& 39 | f(cx); // T is const int, 40 | // param's type is const int& 41 | f(rx); // T is const int, 42 | // param's type is const int& 43 | 44 | You wrote "type deduction works exactly the same way for rvalue 45 | reference parameters." 46 | My second question is why you wrote about rvalue reference parameters 47 | at this point. The rvalue reference parameters is not universal 48 | reference parameters. Do you mean non template rvalue reference 49 | parameters such as int&&? or non deduced template parameters with &&? 50 | Anyway, I don't make sense why you wrote about that at this point. 51 | 52 | My friends and I held the study group of EMC++ in Japan. It's so fun:) 53 | One of atendee has the question above. I read again item1 carefully. 54 | But I don't get the answer. 55 | 56 | Thanks 57 | Takatoshi 58 | ``` 59 | 60 | ##### Scott→私 61 | 62 | ``` 63 | | This question is about 2015-01-20: Third Release. 64 | | 65 | | Item1 page 12, there is the following paragraph: 66 | | ----- 67 | | These examples all show lvalue reference parameters, but type 68 | | deduction works 69 | | exactly the same way for rvalue reference parameters. Of course, only 70 | | rvalue arguments 71 | | may be passed to rvalue reference parameters, but that restriction has 72 | | nothing 73 | | to do with type deduction. 74 | | ----- 75 | 76 | [...] 77 | 78 | | Anyway, I don't make sense why you wrote about that at this point. 79 | | 80 | | My friends and I held the study group of EMC++ in Japan. It's so fun:) 81 | | One of atendee has the question above. I read again item1 carefully. 82 | | But I don't get the answer. 83 | 84 | That's because what I wrote is completely wrong, and I'm very glad that you brought this to my attention. I just added the following errata entry for page 12 to the book's errata page (http://www.aristeia.com/BookErrata/emc++-errata.html ): 85 | 86 | The third paragraph (beginning with "These examples all 87 | show lvalue reference parameters, but type deduction 88 | works exactly the same way for rvalue reference 89 | parameters") should be removed. When the type of param 90 | in the template f on page 11 is changed to an rvalue 91 | reference (i.e., to have type "T&&"), it becomes a 92 | universal reference, and then the rules for Case 2 93 | (on pages 13-14) apply. 94 | 95 | I apologize for this error in the book. I'll fix it when I next get a chance to make revisions. 96 | 97 | Thanks again to you and your colleague for reporting this issue. 98 | 99 | 100 | 101 | Scott 102 | ``` 103 | 104 | ##### 私→Scott 105 | 106 | ``` 107 | Hi Scott, 108 | 109 | Thank you for the reply. I understood it clearly now. Can I forward 110 | this email to the members of study group? I believe that they would be 111 | glad to hear your reply. 112 | 113 | Here are the members of the study group: 114 | https://atnd.org/events/60511 115 | 116 | Thanks 117 | Takatoshi 118 | ``` 119 | 120 | ##### Scott→私 121 | 122 | ``` 123 | | Thank you for the reply. I understood it clearly now. Can I forward 124 | | this email to the members of study group? I believe that they would be 125 | | glad to hear your reply. 126 | 127 | Of course. 128 | 129 | | Here are the members of the study group: 130 | | https://atnd.org/events/60511 131 | 132 | Thanks for this link. 133 | 134 | Scott 135 | ``` 136 | 137 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Effective Modern C++勉強会 2 | 3 | 4 | ## 資料置き場 5 | 6 | ### [本家errata](http://www.aristeia.com/BookErrata/emc++-errata.html) 7 | 8 | ### [第1回 2015/1/28](https://atnd.org/events/60511) 9 | 10 | * [Item 1, 2の資料](http://www.slideshare.net/herumi/template-44013078) : [@herumi](https://twitter.com/herumi) 11 | * [Item 3, 4の資料](http://www.slideshare.net/starpos/effective-modern-c-1-item34) : [@starpoz](https://twitter.com/starpoz) 12 | * [Item 5, 6の資料](http://www.slideshare.net/taka111/emcpp0506) : [@redboltz](https://twitter.com/redboltz) 13 | 14 | ### [第2回 2015/2/25](https://atnd.org/events/62014) 15 | 16 | * Item 7, 8 : [@Talos208](https://twitter.com/Talos208) 17 | * [Item 9, 10の資料](http://www.slideshare.net/uchan_nos/effective-modern-c-2pptx) : [@uchan_nos](https://twitter.com/uchan_nos) 18 | * [Item 11の資料](http://www.slideshare.net/KeisukeFukuda/effective-modern-c2-item1011) : [@keisukefukuda](https://twitter.com/keisukefukuda) 19 | 20 | ### [第3回 2015/3/25](https://atnd.org/events/63259) 21 | 22 | * [Item 12の資料](http://www.slideshare.net/KeisukeFukuda/effective-modern-c-3) : [@keisukefukuda](https://twitter.com/keisukefukuda) 23 | - [blog](http://freak-da.hatenablog.com/entries/2015/03/26) 24 | * Item 13, 14 : [@pepshiso](https://twitter.com/pepshiso) 25 | * [Item 15の資料](http://www.slideshare.net/kariya_mitsuru/effective-modern-c-3-item-15) : [@kariya_mitsuru](https://twitter.com/kariya_mitsuru) 26 | 27 | ### [第4回 2015/4/22](https://atnd.org/events/64371) 28 | 29 | * [Item 16の資料](http://www.slideshare.net/kariya_mitsuru/effective-modern-c-3-item16) : [@kariya_mitsuru](https://twitter.com/kariya_mitsuru) 30 | * [Item 17, 18の資料](http://www.slideshare.net/rigarash/effective-modern-c4-item-17-18) : [@rigarash](https://twitter.com/rigarash) 31 | * [Item 19, 20の資料](https://speakerdeck.com/rhysd/effective-modern-c-plus-plus-item19-item20) : [@linda_pp](https://twitter.com/linda_pp) 32 | 33 | ### [第5回 2015/5/20](https://atnd.org/events/65442) 34 | 35 | * [Item 21の資料](http://www.slideshare.net/herumi/emcjp-item21) [@herumi](https://twitter.com/herumi) 36 | * [Item 22の資料](http://www.slideshare.net/KeisukeFukuda/effective-modern-c-item-22) [@keisukefukuda](https://twitter.com/keisukefukuda) 37 | * [Item 23の資料](http://www.slideshare.net/uchan_nos/effective-modern-c-5) [@uchan_nos](https://twitter.com/uchan_nos) 38 | * [Item 24の資料](http://www.slideshare.net/mooopan/emc24) [@mooopan](https://twitter.com/mooopan) 39 | 40 | ### [第6回 2015/6/17](https://atnd.org/events/66415) 41 | 42 | * [Item 25の資料](http://www.slideshare.net/starpos/effective-modern-c-6-item25) [@starpoz](https://twitter.com/starpoz) 43 | * [Item 26の資料](http://www.slideshare.net/barfoo102/emc-26) [@regenschauer490](https://twitter.com/regenschauer490) 44 | * [Item 27の資料](http://www.slideshare.net/kariya_mitsuru/effective-modern-c-7-item-27) : [@kariya_mitsuru](https://twitter.com/kariya_mitsuru) 45 | * Item 28 [@redboltz](https://twitter.com/redboltz) 46 | 47 | ### [第7回 2015/7/15](https://atnd.org/events/67443) 48 | 49 | * [Item 29, 30の資料](https://speakerdeck.com/rhysd/effective-modern-c-plus-plus-du-shu-hui-item29-item30) : [@Linda_pp](https://twitter.com/Linda_pp) 50 | * [Item 31の資料](http://www.slideshare.net/mitsutaka_takeda/emcpp-item31) : [@MitsutakaTakeda](https://twitter.com/MitsutakaTakeda) 51 | * [Item 32の資料](http://www.slideshare.net/simizut22/emc-chapter32) : [@simizut22](https://twitter.com/simizut22) 52 | * [Item 33, 34の資料](http://www.slideshare.net/herumi/emcjp-item3334) : [@herumi](https://twitter.com/herumi) 53 | 54 | ### [第8回 2015/8/19](https://atnd.org/events/68406) 55 | 56 | * [Item 35の資料](http://www.slideshare.net/KeisukeFukuda/effective-modern-c-item-35) : [@keisukefukuda](https://twitter.com/keisukefukuda) 57 | * [Item 36の資料](http://www.slideshare.net/simizut22/effective-modern-cchapeter36) : [@simizut22](https://twitter.com/simizut22) 58 | * [Item 37の資料](http://www.slideshare.net/uchan_nos/effective-modern-c-8 ) : [@uchan_nos](https://twitter.com/uchan_nos) 59 | * [Item 38の資料](http://www.slideshare.net/starpos/effective-modern-c-8-item38) : [@starpoz](https://twitter.com/starpoz) 60 | 61 | ### [第9回 2015/9/30](https://atnd.org/events/69460) 62 | 63 | * [Item 39の資料](http://www.slideshare.net/taka111/effective-modern-c-study-group-item39) : [@redboltz](https://twitter.com/redboltz) 64 | * [Item 40の資料](http://www.slideshare.net/simizut22/effective-modernc9) : [@simizut22](https://twitter.com/simizut22) 65 | * [Item 41の資料](http://www.slideshare.net/mitsutaka_takeda/emcpp-item41) : [@MitsutakaTakeda](https://twitter.com/MitsutakaTakeda) 66 | * [Item 42の資料](http://www.slideshare.net/herumi/emcjp-item-42) : [@herumi](https://twitter.com/herumi) 67 | 68 | ### 疑問やコメントなど(随時思い出したら書く) 69 | 70 | [memo.md](memo.md) 71 | 72 | ### Item 39. 73 | 74 | * ポーリングのtips 75 | Intelにはbusy loopを検知してCPUパフォーマンスをあげて電力消費を減らすpause命令がある。 76 | 77 | 参考:[Benefitting Power and Performance Sleep Loops](https://software.intel.com/en-us/articles/benefitting-power-and-performance-sleep-loops) 78 | 79 | * 条件変数のwaitは、イベントが本当に発生したらtrueを返すラムダ式と一緒に使うべき。 80 | 偽の起動(spurious wakeup)があるため。 81 | 82 | 参考:[条件変数とspurious wakeup](http://d.hatena.ne.jp/yohhoy/20120326/) 83 | 84 | Q. vector vtにemplace_backしている途中で例外が発生したらset_valueするまえに抜けるのでブロックする可能性がある? 85 | 86 | A. scope_exitをthreadを生成するループの前に置くとよいだろう。 87 | 88 | ### Item 40. 89 | Q. intとかの整数型はいつでもlockでatomicを実現するの? 90 | 91 | A. アーキテクチャによって違う。Intel系でも32bit環境でint64_tだと結構複雑。 92 | VCだと`_InterlockedExchangeAdd64`, clangだと_atomic_fetch_add_8を呼ぶ。 93 | gccだとinlineでlock cmpxchg8bとloopの組み合わせ. 94 | ``` 95 | .L2: 96 | movl %eax, %ecx 97 | movl %edx, %ebx 98 | addl $1, %ecx 99 | adcl $0, %ebx 100 | movl %ebx, %ebp 101 | movl %ecx, %ebx 102 | movl %ebp, %ecx 103 | lock cmpxchg8b (%esi) 104 | jne .L2 105 | ``` 106 | 107 | volatileの細かい仕様は各コンパイラの処理系依存。 108 | 規格上CとC++でも違う。以下雑多なメモ。 109 | ``` 110 | void f(int *nv1, int *nv2, volatile int *v) 111 | { 112 | *nv1 = 1; 113 | *nv2 = 2; 114 | *v = 3; 115 | *nv2 = 4; 116 | *v = 5; 117 | *nv1 = 6; 118 | } 119 | ``` 120 | VC, clangでは1, 2, 3, 4, 5, 6全ての書き込み命令がその順序で生成された。 121 | ``` 122 | // VC2015 123 | mov DWORD PTR [rcx], 1 124 | mov DWORD PTR [rdx], 2 125 | mov DWORD PTR [r8], 3 126 | mov DWORD PTR [rdx], 4 127 | mov DWORD PTR [r8], 5 128 | mov DWORD PTR [rcx], 6 129 | ``` 130 | ``` 131 | // clang 3.5 132 | movl $1, (%rdi) 133 | movl $2, (%rsi) 134 | movl $3, (%rdx) 135 | movl $4, (%rsi) 136 | movl $5, (%rdx) 137 | movl $6, (%rdi) 138 | ``` 139 | gcc-4.8では1, 2の書き込みは消えた。 140 | ``` 141 | movl $3, (%rdx) 142 | movl $4, (%rsi) 143 | movl $5, (%rdx) 144 | movl $6, (%rdi) 145 | ``` 146 | 147 | * [MSDN](https://msdn.microsoft.com/ja-jp/library/12a04hfd.aspx) 148 | * [clang](http://llvm.org/docs/Atomics.html) 149 | * [gcc](https://gcc.gnu.org/onlinedocs/gcc/Volatiles.html) 150 | volatileの最低限の要件は、シーケンスポイントにおいてvolatile変数より前の全てのアクセスが完了し、後続するアクセスは起こらないこと。 151 | シーケンスポイント間のvolatileアクセスの順序入れ替えや結合は許可されている。 152 | シーケンスポイントを越えてのその操作はできない。 153 | 154 | 非volatileへのアクセスはvolatileへのアクセスに関して順序づけられない。 155 | volatile変数を非volatileメモリへの書き込みの順序づけのためのメモリバリアには使えない。 156 | ``` 157 | int *ptr = something; 158 | volatile int vobj; 159 | *ptr = something; 160 | vobj = 1; 161 | ``` 162 | vobjへの書き込みが起こるまでに*ptrへの書き込みがあることは保証されない。 163 | ``` 164 | int *ptr = something; 165 | volatile int vobj; 166 | *ptr = something; 167 | asm volatile ("" : : : "memory"); 168 | vobj = 1; 169 | ``` 170 | しないといけない。 171 | 172 | * [g++](https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Volatiles.html) 173 | ``` 174 | void f(volatile int *v) 175 | { 176 | *v; 177 | } 178 | ``` 179 | C++的には*v;をlvalueからrvalueへの変換をしない。脱参照された型は不完全かもしれない。 180 | その変換がメモリアクセスを引き起こすかどうかは明記しない。 181 | しかし、それだと大抵のプログラマが驚くのでg++ではvolatileオブジェクトの脱参照はCと同じに扱う。 182 | ``` 183 | movl (%rdi), %eax ; アクセス発生 184 | ret 185 | ``` 186 | VCも同様に残す。 187 | clangはCでbuildすると残す。C++では残さない。 188 | ``` 189 | clang -x c -S -Ofast t.c 190 | f: 191 | movl (%rdi), %eax 192 | retq 193 | ``` 194 | ``` 195 | clang -x c++ -S -Ofast t.c 196 | f: 197 | retq 198 | ``` 199 | cf. シーケンスポイント 200 | `&&`の左側, `||'の左側, コンマ演算子の左側, 関数の呼び出し, 条件演算子の最初のオペランド, 完全な初期化式の終わり, 式ステートメントの式, 201 | if, switchないの制御式, while, doの制御式, forの3つの式, returnの式 202 | 203 | # Item 41. 204 | Q. shared_ptrなどはconst&で渡す? 205 | 206 | A. 生ポインタを渡すこともある。あとconst shared_ptrはconstと紛らわしいのであまり使わないかも。 207 | 208 | ``` 209 | #include 210 | #include 211 | 212 | struct A { 213 | A(int a) : a(a) { printf("cstr %d\n", a); } 214 | ~A() { printf("dstr %d\n", a); } 215 | int a; 216 | }; 217 | 218 | void f(const std::shared_ptr& a) 219 | { 220 | a.get()->a = 5; // 書き換え可能 221 | } 222 | 223 | int main() 224 | { 225 | std::shared_ptr a = std::make_shared(3); 226 | f(a); 227 | } 228 | ``` 229 | 230 | * slideの最後に上げられている参考文献へのリンク 231 | * [Keynote: The Evolving Search for Effective C++ by Scott Meyers](http://meetingcpp.com/index.php/tv14/items/23.html) 232 | * Item 42のpush_backとemplace_backの話もでている。 233 | * [Back to the Basics! Essentials of Modern C++ Style by Herb Sutter](https://isocpp.org/blog/2015/02/cppcon-2014-back-to-the-basics-essentials-of-modern-c-style-herb-sutter) 234 | * cstrのみ値渡しという手法の提案 235 | -------------------------------------------------------------------------------- /memo.md: -------------------------------------------------------------------------------- 1 | ### Item 1 p.12の 2 | 3 | >These examples all show lvalue reference parameters, but 4 | >type deduction works exactly the same way for rvalue reference parameters. 5 | 6 | の意味が分からない。[テキストの間違い](misc/mail.md) 7 | 8 | ### Item 2のauto a{3}がinitializer_listになるのは気持ち悪い。 9 | 10 | C++17で仕様変更された(by [@pepshiso](https://twitter.com/pepshiso/status/560384555257851904))。 11 | [New Rules for auto deduction from braced-init-list](http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2014/n3922.html) 12 | 13 | ``` 14 | // C++11, C++14 C++17 15 | auto x = {1}; // 初期化リスト 初期化リスト 16 | auto x = {1, 2}; // 初期化リスト 初期化リスト 17 | auto x{1}; // 初期化リスト int 18 | auto x{1, 2}; // 初期化リスト error 19 | ``` 20 | 21 | ### Item 3のdecltype(x)とdecltype((x))で意味が変わる例 22 | 23 | ``` 24 | // C++14 only 25 | decltype(auto) f2() 26 | { 27 | static int x = 0; 28 | return (x); // ここをreturn xにするとコンパイルエラーになる。 29 | } 30 | 31 | int main() 32 | { 33 | printf("f2()=%d\n", f2()); 34 | f2() = 3; 35 | printf("f2()=%d\n", f2()); 36 | } 37 | ``` 38 | 39 | ### Item 6のvectorのoperatorをautoで受けると駄目な話。 40 | 41 | [item6-1.cpp](https://github.com/herumi/emcjp/blob/master/src/item6-1.cpp) 42 | VecがintではなくRefを返す。 43 | intで受けるとRef()からintに変換されてから一時オブジェクトのVecとRefが消滅する。 44 | 45 | autoで受けるとRef()のままになり、Refの寿命はあるけどそれが参照しているVecは先に消滅するのでそのあとintに変換するとアウト。 46 | ``` 47 | use int 48 | Vec cstr 49 | Ref cstr 50 | read x 51 | Ref dstr 52 | Vec dstr 53 | type=int a=5 54 | use auto 55 | Vec cstr 56 | Ref cstr 57 | Vec dstr 58 | read x 59 | type=struct Ref a=5 60 | Ref dstr 61 | ``` 62 | 63 | ### std::vector::size_typeはsize_tで受けてよいのか? 64 | 65 | 問題になるとは思えないがどこかで保証してる? 66 | 67 | ### Item 7 68 | 69 | * `{}`のメリット 70 | * 適用可能なケースが多い 71 | * 間違えてnarrowingしてしまう可能性が低い 72 | * Most Vexing Parse(変数宣言が関数のプロトタイプになってしまうやつ)の心配がない 73 | * `()`のメリット 74 | * C++98の文法と互換 75 | * initializer_listに関する問題がない 76 | 77 | templateの中で一次オブジェクトを作るとき、`{}`と`()`のどちらを使っているかドキュメントに書かないと利用する人はわからないことがある。 78 | [item7-3.cpp](https://github.com/herumi/emcjp/blob/master/src/item7-3.cpp) 79 | 80 | ### Item 8 81 | 整数型とポインタのオーバーロードは止めよう 82 | 83 | ### Item 9 84 | 85 | typedef vs. using 86 | * usingはtemplate化が可能。使うときは`typename`は要らない。`::type`も要らない。 87 | * typedefのときはdependent type 88 | * usingはnon-dependent type 89 | * C++14ではremove_constなどに_tバージョンが追加された。 90 | * [本家eratta 1/25/15 tyk All](http://www.aristeia.com/BookErrata/emc++-errata.html)にtypedefよりalias templateがよい例が載ってる。 91 | 92 | Q. alias templateは特殊化できないけどどうなんだ。→ templateクラスのラップ 93 | * 元のクラスの特殊化と区別できないからしかたない? 94 | * 使う人からするとそんなことを気にせず特殊化したい? 95 | 96 | ### Item 10 97 | enum Class使え。 98 | 99 | Visual Studioでは 100 | ``` 101 | enum X { 102 | x = 1234567890123ull 103 | }; 104 | ``` 105 | は32bitを超えた部分が切り捨てられる。 106 | ``` 107 | enum class X:long long { 108 | x = 1234567890123ull 109 | }; 110 | ``` 111 | ならOK。 112 | 113 | ### Item 11 114 | * 代入演算子を使えなくするにはprivateじゃなくて`= delete`の方がいい。 115 | * `= delete`はprivateじゃなくてpublicに書く方がいい。 116 | * コンパイラはdeletedかどうかより先にaccessibilityをチェックするため。 117 | 118 | 普通の関数でも`= delete`は使える。 119 | templateでdefault deleteにして使いたいのだけ特殊化、あるいはオーバーロードする。 120 | ``` 121 | #include 122 | template 123 | void f(T) = delete; 124 | 125 | void f(int) { puts("int"); } 126 | 127 | int main() 128 | { 129 | f(3); 130 | f('a'); // deleteがないとintにmatchしてしまう。 131 | } 132 | 133 | ``` 134 | * char32_tなどは予約語なので`std::`は要らない(erattaに連絡済み)。 135 | 136 | ### Item 12 137 | override使う。 138 | gccでは-Wall, -Wextraの他に-Woverloaded-vitrualが必要 139 | 140 | メンバ関数のreference qualifierのメリットの例 141 | 142 | `a + b = 3`を防げる。 143 | ``` 144 | struct X { 145 | friend inline X operator+(const X&, const X&) { return X(); } 146 | X& operator=(int) { return *this; } 147 | X& operator=(const char*) & { return *this; } 148 | }; 149 | 150 | int main() 151 | { 152 | X a, b; 153 | a + b = 3; // 通ってしまう 154 | a + b = "a"; // &がついてるとエラーにできる 155 | } 156 | ``` 157 | 158 | reference qualifierをつけまくったときでgccがambigiousでエラーになるのは4.9.1から直ってました。 159 | [item12-1.cpp](src/item12-1.cpp) 160 | 161 | ### Item 13 162 | C++03はconst_iteratorは冷遇されていた。C++11からはcbegin, cendを使う。 163 | C++14からはグローバル関数のcbegin, cendを使う。 164 | ### Item 14 165 | スタックの巻き戻しに必要なコードを減らせるため可能ならthrow()よりもnoexceptを使う。 166 | ``` 167 | #include 168 | #include 169 | 170 | struct A { 171 | A() { puts("cstr"); } 172 | ~A() { puts("dstr"); } 173 | }; 174 | 175 | void f_noexcept() noexcept { 176 | A a; 177 | throw 1; 178 | } 179 | 180 | void f_nothrow() throw() { 181 | A a; 182 | throw 1; 183 | } 184 | 185 | int main() 186 | { 187 | #ifdef NOEXCEPT 188 | puts("noexcept"); 189 | f_noexcept(); 190 | #else 191 | puts("throw()"); 192 | f_nothrow(); 193 | #endif 194 | } 195 | ``` 196 | throw()版なら 197 | ``` 198 | terminate called after throwing an instance of 'int' 199 | 200 | noexcept 201 | cstr 202 | dstr 203 | ``` 204 | dstrが呼ばれてからstd::unexpected()が呼ばれ、それがstd::terminate()になっている。 205 | noexceptならdstrを呼ばずに即座にstd::terminate()を呼ぶ。 206 | ``` 207 | terminate called after throwing an instance of 'int' 208 | 209 | noexcept 210 | cstr 211 | ``` 212 | ただし今のところこの最適化はgccのみ。clang(-3.7)では変わらない。 213 | 214 | ### Item 15 215 | * 可能ならconstexprを使え。 216 | * メンバ関数のconstexprにはconstもつけること(C++14で挙動が変わる)。 217 | * setterにconstexprをつけるとよいことがある。 218 | 219 | ``` 220 | #include 221 | #include 222 | 223 | struct A { 224 | static constexpr std::pair p{3,5}; 225 | }; 226 | 227 | int main() 228 | { 229 | printf("A::p.first=%d\n", A::p.first); 230 | } 231 | ``` 232 | がgccでエラーになるのはバグ? コードが悪い? 233 | => 多分バグ 234 | 235 | ### Item 19 236 | 共有リソースの管理にはshared_ptrを使う。 237 | [Cryoliteさんの昔の解説記事](http://d.hatena.ne.jp/Cryolite/20060108) 238 | * すぐ戻ってくる関数で使うならcopyよりmoveの方が参照カウンタが増えないのでいい。 239 | * shared_ptrで確保したインスタンスのthisを別のshared_ptrに渡してはいけない。 240 | - enable_shared_from_thisを継承してshared_from_thisを使う。 241 | 242 | ### Item 20 243 | ちゅうぶらりん(dangling)になるかもしれないshared_ptrに対してはweak_ptrを使う。 244 | 245 | ``` 246 | auto s = std::make_shared(); 247 | std::weak_ptr w(s); 248 | 249 | if (w.expired()) { 250 | ... /// XXX 251 | } 252 | ``` 253 | この方法だとw.expired()がtrueでもXXXの時点で 254 | sが他のスレッドで解放されてfalseになってるかもしれないので使うべきではない。 255 | 256 | ``` 257 | if (auto p = w.lock()) { 258 | ... 259 | } 260 | ``` 261 | の形だとshared_ptrへの変換と判定がatomicに行われるのでよい。 262 | 263 | ### Item 21 264 | 265 | unique_ptrやshared_ptrよりはmake_unique(from C++14)やmake_sharedを使おう。 266 | ただしmake_sharedはいろいろ罠があるので気をつける。 267 | make_sharedを使うとT::operator newが呼ばれないのはもっと明記した方がよいような。 268 | 269 | Q. use_count()の戻り値がsize_tではなくlongなのはなぜ? boostのときからそうだけど。 270 | 271 | ### Item 16 272 | constメンバ関数はthread safeにすべき。 273 | 274 | ### Item 17 275 | 特殊なメンバ関数の自動生成を理解する。 276 | moveされることを期待するならちゃんと書く。 277 | 自明なdstrを定義すると暗黙のmoveはcopyになってしまうので注意する。 278 | ### Item 18 279 | auto_ptrの代わりにunique_ptrを使う。 280 | カスタムdeleterは関数よりlambdaの方が効率がよい。 281 | 282 | * Q. socketやfile descriptorなどはポインタ型でないのでshared_ptrとか使いにくい。 283 | * A. see [Resource Management with Explicit Template Specializations](http://accu.org/index.php/journals/2086) 284 | 285 | ### Item 22 286 | pImplの実装にunique_ptrを使う。 287 | cppに特殊メンバ関数をきちんと書かなければならない。 288 | pImplがnullptrになっているとき(自分自身もrhsも)を考慮したcopy cstrやoperator=を書く必要がある。 289 | 290 | たとえば 291 | ``` 292 | std::string a = "abc"; 293 | std::string b(std::move(a)); 294 | ``` 295 | したとき、`a.c_str()`の値は未規定(unspecified)ではあるが、`valid state`ではあるのでsegvしてはいけない。 296 | valid stateってなんだよという疑問はあるが。 297 | 本は間違ってるので注意(最新版pdfでは修正されているらしい)。 298 | たとえばこんな感じ。 299 | ``` 300 | class A { 301 | .... 302 | private: 303 | struct Impl; 304 | std::unique_ptr pImpl_; 305 | }; 306 | 307 | A::A(const A& rhs) 308 | : pImpl_(std::unique_ptr(rhs.pImpl_ ? new Impl(*rhs.pImpl_) : new Impl())) 309 | { 310 | } 311 | 312 | A& A::operator=(const A& rhs) 313 | { 314 | if (rhs.pImpl_) { 315 | if (pImpl_) { 316 | *pImpl_ = *rhs.pImpl_; 317 | } else { 318 | pImpl_.reset(new Impl(*rhs.pImpl_)); 319 | } 320 | } else { 321 | pImpl_.reset(); 322 | } 323 | return *this; 324 | } 325 | ``` 326 | そのあたりはmake_sharedを使うと楽になるよと書いてあるが、make_sharedを使うとインスタンスは共有されるので元のクラスの意味と違ってしまうので要注意(こちらも最新pdfでは記載されているらしい)。 327 | 328 | ### Item 23 329 | 330 | std::moveやstd::forwardは単なるremove_reference_t&&へのキャスト。 331 | std::moveはTの型を明示しなくてよいがstd::forwardは明示する必要がある。 332 | 333 | Q. std::moveをconst T&&に対してエラーするのはどうか。 334 | 335 | ### Item 24 336 | templatevoid f(T&& param)やauto&&などの型推論が行われるところでのみ 337 | T&&は右辺値にも左辺値にも束縛される可能性がある。 338 | * lvalueで初期化するとlvalue referenceになる。 339 | * rvalueで初期化するとrvalue referenceになる。 340 | 著者はuniversal referenceという言葉を推している。 341 | 342 | ### Item 25 343 | 右辺値参照にはstd::move, universal参照にはstd::forwardを使う。 344 | * moveのほうが短くてよいけどしてほしくないときにmoveされてしまうことがある。 345 | ``` 346 | struct A { 347 | template 348 | void set(T&& rhs) 349 | { 350 | a = std::move(rhs); 351 | } 352 | std::string a; 353 | }; 354 | std::string getName() { return "abc"; } 355 | ``` 356 | ``` 357 | A a; 358 | std::string n = getName(); 359 | a.set(n); 360 | // nの値は不明。 361 | ``` 362 | 363 | ``` 364 | A f(A a) { 365 | return a; 366 | } 367 | ``` 368 | はRVO, NRVOではないがstd::moveされる。 369 | 370 | Q. `A operator+(A&& lhs, const A&& rhs)`でAを返すのは何故? 371 | A. a + b + cみたいにしたいから。std::stringのoperator+はいろんなパターンのオーバーロードで頑張ってる。 372 | 373 | ### Item 26 374 | universal参照のoverloadを避ける。 375 | ``` 376 | struct A { 377 | void set(const std::string& a) { this->a = a; } 378 | std::string a; 379 | }; 380 | ``` 381 | set("abc"), set(std::string("abc"))などで効率がよくない。 382 | 383 | ``` 384 | struct A { 385 | template 386 | void set(T&& a) { this->a = std::forward(a); } 387 | std::string a; 388 | }; 389 | ``` 390 | なら効率がよい。 391 | しかしset(int idx)を追加すると`short a; set(a)`がコンパイルエラー。 392 | 393 | オーバーロードのマッチの優先順位 394 | 1. 非関数templateで引数が一番マッチする 395 | 2. 関数templateでtemplate argument deductionで1と同じシグネチャにマッチする 396 | 3. 暗黙の型変換でマッチする 397 | 398 | コンストラクタが困ってしまう。 399 | 400 | * 値"abc"に変数(name)を束縛する(bind)。逆に言い間違えやすい。 401 | 402 | ### Item 27 403 | universal ref以外のオーバーロード 404 | 405 | メモ書き 406 | 407 | * univresal refは知らないとトラブルになりやすい。思った通りに動いてくれば問題ない。 408 | 409 | 解決法 410 | 411 | 1. overloadを諦める。 412 | 413 | * 名前を変えればよい。 414 | * 欠点 : cstrには無力(名前が無い)。 415 | 416 | 2. const T&で渡す。 417 | 418 | * 欠点:universal refほど効率的ではない。シンプルさは魅力的。 419 | 420 | 3. 値で渡す。 421 | 422 | * 効率はわりといい。universal refほどではない。Item 41で。 423 | * 欠点 : std::moveが効率悪いと駄目。 424 | * 0はともかくNULLを渡すとintになる。 425 | 426 | 4. tag dispatch 427 | 428 | * universal refの欠点 429 | * 欠点 : あらゆるものにマッチする。 430 | * universal refで引数を増やせばよい。 431 | * Tがintとint以外で異なるものにdispatch 432 | * 欠点 : cstrには無力 433 | 434 | 5. universal refをとるtemplateに制約を設ける 435 | 436 | * 関数を呼ばれてほしいときだけ有効にする : std::enable_if ; SFNIAE 437 | * 欠点 : エラーが読めない 438 | 439 | 440 | こういう書き方もある。 441 | ``` 442 | #include 443 | #include 444 | #include 445 | 446 | template::value>::type* = 0> 447 | void f(T&&) 448 | { 449 | puts("integral"); 450 | } 451 | 452 | int main() 453 | { 454 | f(3); 455 | } 456 | ``` 457 | 458 | Q. シグネチャに戻り値を含むのだっけ。 459 | 460 | A. http://stackoverflow.com/questions/290038/is-the-return-type-part-of-the-function-signature 461 | 普通の関数は、戻り値の型をシグネチャに含まない。関数テンプレートの特殊化は含む。 462 | 463 | ###Item 28 464 | 参照の畳み込み(collapsing)を理解する 465 | 畳み込みが起こる場所 466 | * templateのinstantiation 467 | * autoの型生成 468 | * typedefとusing 469 | * decltype 470 | ``` 471 | & & => & 472 | && & => & 473 | & && => & 474 | && && => && 475 | ``` 476 | 477 | ### Item 29 478 | std::moveがいつでもできて軽いというわけじゃないので気をつけよう。 479 | 480 | VC2013がデフォルトのmove cstrを作らないので悲しい。VC2015は大丈夫。 481 | ### Item 30 482 | perfect forwardingが失敗する例。 483 | 484 | * 初期化リスト(non deduced context)。autoのときと同じ(item 2) 485 | * ポインタとしての0やNULL 486 | * static const data 487 | ``` 488 | #include 489 | #include 490 | 491 | struct A { 492 | static const int a = 3; 493 | }; 494 | 495 | void f(int x) { printf("%d\n", x); } 496 | 497 | template 498 | void fwd(T&& p) { f(std::forward(p)); } 499 | 500 | int main() 501 | { 502 | // f(A::a); 503 | fwd(A::a); 504 | } 505 | ``` 506 | これがリンクエラーになるので要注意(gcc -O0)。 507 | ``` 508 | const int A::a; 509 | ``` 510 | が必要。 511 | 512 | ### Item 31 513 | [資料](http://www.slideshare.net/mitsutaka_takeda/emcpp-item31)が詳しいのでそちらを参照。 514 | 引数のキャプチャにはby-valueとby-referenceの二つがある。 515 | 変数の寿命に十分注意すること。 516 | 517 | lambda式を定義と同時に呼び出すときは&でいいのではという案。 518 | ``` 519 | const auto size = [&]{ return condition ? 1 : 2; }(); 520 | ``` 521 | 522 | Q. lambdaの中で使われなかった変数はコピーされる? 523 | 524 | A. 実際に使われた変数のみがコピーされる. 明示した場合はコピーされる. 525 | ### Item 32 526 | C++14ではキャプチャ時にmoveできるようになった。 527 | ``` 528 | auto func = [pw = std::move(pw)]{ pw->isValidate(); }; 529 | ``` 530 | 補足: gcc-5.xでは 531 | ``` 532 | auto func = [pw{std::move(pw}]{ pw->isValidate(); }; 533 | ``` 534 | という書き方もできる。 535 | 536 | C++11ではstd::bindを組み合わせればできる。 537 | 538 | Q. でも一時的なものだったらクラスを明示的に作った方がわかりやすくていいんじゃないか? 539 | 540 | ### Item 33 541 | C++14で導入されたgeneric lambda。 542 | その中でstd::forwardしたいときはdecltypeを使う。 543 | ``` 544 | auto f = [](auto&& x) { 545 | return func(normalize(std::forward(x))); 546 | } 547 | ``` 548 | ### Item 34 549 | * C++11で入ったstd::bindはC++14で入ったmoveキャプチャ可能なlambdaとgeneric lambdaのおかげで不要になった。 550 | * std::bindを使うときは、bindするときに呼びたくない関数はbindを重ねる必要がある。 551 | Meyersが間違えるぐらいにややこしいので使わない方が無難。 552 | --------------------------------------------------------------------------------