Skip to content

Commit f9476e4

Browse files
committed
constexpr
1 parent ebad603 commit f9476e4

File tree

6 files changed

+152
-9
lines changed

6 files changed

+152
-9
lines changed

understanding-c++11/constexpr.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#include "constexpr.h"
2+
NS_BEGIN(elloop)
3+
NS_BEGIN(constexpr)
4+
5+
TEST(Constexpr, UseDefinedConstData) {
6+
#ifdef _MSC_VER
7+
#else
8+
EXPECT_EQ(6, birthMonth);
9+
#endif
10+
}
11+
NS_END(constexpr)
12+
NS_END(elloop)

understanding-c++11/constexpr.h

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#ifdef _MSC_VER
2+
#pragma once
3+
#else
4+
_Pragma("once")
5+
#endif
6+
#include "inc.h"
7+
8+
NS_BEGIN(elloop)
9+
NS_BEGIN(constexpr)
10+
11+
#ifdef _MSC_VER
12+
#else
13+
//---------------------- const expression function ----------------------
14+
// Four condition:
15+
// 1. function body can contain only a return statement(except for use,typedef...)
16+
// 2. must have return value(cannot be void).
17+
// 3. must be defined, before using.
18+
// 4. return statement cannot contains: non-const expression, global data.
19+
// it must be a const expression.
20+
21+
// example:
22+
constexpr int data() { const int i = 1; return i;} // wrong, too many statements.
23+
constexpr void f() {} // wrong, must have return val.
24+
25+
constexpr int cf();
26+
constexpr int c = cf(); // wrong, cf is not defined.
27+
28+
int globalInt(100);
29+
constexpr int g() { return globalInt; } // wrong, global data..
30+
31+
int nonConstFunc() { return 1;}
32+
constexpr int k() { return nonConstFunc(); } // wrong, nonConstFunc is not const expression.
33+
34+
const int returnConst { return 11;}
35+
constexpr int p() { return returnConst(); } // wrong, returnConst is not const expression.
36+
37+
//---------------------- const expression value ----------------------
38+
// 1.
39+
// const int j=1;
40+
// constexpr int j = 1;
41+
// what's the difference?
42+
// const's j, 如果j在全局的名字空间,编译器一定会为它产生数据;
43+
// constexpr's j 编译器不会为它生成数据(除非代码显示地使用了它的地址)。
44+
45+
// 2. user defined const expression data.
46+
// Two rules:
47+
// 1. constexpr constructor must empty body.
48+
// 2. initial list can only use constexpr expression.
49+
50+
struct Data {
51+
constexpr Data(int y, int m, int d) : year(y), month(m), day(d) {}
52+
constexpr int year() {return year;}
53+
constexpr int month() {return month;}
54+
constexpr int day() {return day;}
55+
private:
56+
int year;
57+
int month;
58+
int day;
59+
};
60+
constexpr Data kBirth(1988, 5, 12);
61+
constexpr int birthMonth = kBirth.month();
62+
63+
//---------------------- use in template ----------------------
64+
template <typename T>
65+
constexpr T makeConstexpr(T t) {
66+
return t;
67+
}
68+
69+
struct NonConstexpr {
70+
int i;
71+
NonConstexpr() {i = 1;}
72+
};
73+
74+
void test() {
75+
NonConstexpr n1;
76+
NonConstexpr n2 = makeConstexpr(n1); // constexpr is ignored, because n1 is not constexpr
77+
constexpr int i = makeConstexpr(10); // ok
78+
}
79+
80+
//---------------------- constexpr meta programming ----------------------
81+
constexpr int fib(int n) {
82+
return (n == 1) ? 1 : ((n == 2) ? 1 : fib(n-1) + fib(n-2));
83+
}
84+
85+
int fibs[] = {
86+
fib(11), fib(12), fib(20)
87+
};
88+
89+
90+
91+
#endif
92+
93+
NS_END(constexpr)
94+
NS_END(elloop)

understanding-c++11/rvalue_refrence_and_move_constructor.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ void targetFunction(const int && m) { LOGD("const rvalue reference target\n"); }
108108
void targetFunction(const int & m) { LOGD("const lvalue reference target\n"); }
109109
/*
110110
template <typename T>
111-
void iAmForwarding(T&& t) {
111+
void forwarding(T&& t) {
112112
targetFunction(std::forward<T>(t));
113113
}
114114
*/
@@ -119,10 +119,10 @@ TEST(RValueReference, PerfectForward) {
119119
const int c = 1;
120120
const int d = 0;
121121

122-
iAmForwarding(a);
123-
iAmForwarding(std::move(b));
124-
iAmForwarding(c);
125-
iAmForwarding(std::move(d));
122+
forwarding(a);
123+
forwarding(std::move(b));
124+
forwarding(c);
125+
forwarding(std::move(d));
126126

127127
}
128128

understanding-c++11/rvalue_refrence_and_move_constructor.h

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@ NS_BEGIN( rvalue_refrence_and_move_constructor )
2323
// 1. is_rvalue_reference
2424
// 2. is_lvalue_reference
2525

26-
// ------------------ std::move ------------------
26+
// ------------------ std::move<T> & std::forward<T> ------------------
2727
// std::move is equal to operation: static_cast<T&&>(lvalue)
28+
// std::forward has the same function with std::move, like an alias of move, but
29+
// is specially used for template function forwarding params.
2830
// 强制转换为右值,move(x) 将会调用x的移动构造函数,被转化的x并不会立即被析构,所以
2931
// 注意这个问题,参考 TEST(RValueReference, MoveConstructorTest)
3032

@@ -209,10 +211,37 @@ void targetFunction(const int && m);
209211
void targetFunction(const int & m);
210212

211213
// template function decide the type of t is simple:
212-
// 1. iAmForwarding's param is lvalue_reference -> template param type: T&
213-
// 2. iAmForwarding's param is rvalue_reference -> template param type : T&&
214+
// 1. forwarding's param is lvalue_reference -> template param type: T&
215+
// 2. forwarding's param is rvalue_reference -> template param type : T&&
214216
template <typename T>
215-
void iAmForwarding(T&& t) {
217+
void forwarding(T&& t) {
218+
// QUESTION 1: why not use forwarding(T t)
219+
// key: that will become a copy semantic, pass by value.
220+
221+
// QUESTION 2: figure out
222+
//
223+
// int a;
224+
// forwarding(a);
225+
//
226+
// why std::is_lvalue_reference<T&&>::value == 1 ?
227+
// int&& fail to bind with a ? so becomes a int& instead??
228+
bool same = std::is_same<int&, T&&>::value; // same is true in vs2013.
229+
230+
// AND
231+
// fowarding(move(a)); T is int&&
232+
// so forwarding(int&& && t) -> forwarding(int&& t) [reference folding]
233+
234+
//psln(typeid(decltype(t)).name());
235+
//psln(typeid(T).name());
236+
//psln(std::is_lvalue_reference<T&&>::value);
237+
//psln(std::is_rvalue_reference<decltype(t)>::value);
238+
//targetFunction(std::forward<T>(t));
239+
240+
// NOTICE: 能接受右值的右值引用本身是个左值, 即t是个左值(即使传递进来的确实是个右值)
241+
// 这样直接传递给targetFunction, 就会丢失原来的左右值属性,变成左值引用
242+
// targetFunction(t);
243+
244+
// RIGHT WAY: forward会保持左右值属性.
216245
targetFunction(std::forward<T>(t));
217246
}
218247

understanding-c++11/understanding-c++11.vcxproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
<ClCompile Include="attribute.cpp" />
8484
<ClCompile Include="auto.cpp" />
8585
<ClCompile Include="compatibility.cpp" />
86+
<ClCompile Include="constexpr.cpp" />
8687
<ClCompile Include="constructor_test.cpp" />
8788
<ClCompile Include="decltype.cpp" />
8889
<ClCompile Include="initializer_test.cpp" />
@@ -110,6 +111,7 @@
110111
<ClInclude Include="alignof_alignas.h" />
111112
<ClInclude Include="attribute.h" />
112113
<ClInclude Include="auto.h" />
114+
<ClInclude Include="constexpr.h" />
113115
<ClInclude Include="decltype.h" />
114116
<ClInclude Include="inline_namespace.h" />
115117
<ClInclude Include="lambda_test.h" />

understanding-c++11/understanding-c++11.vcxproj.filters

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@
7171
<ClCompile Include="rvalue_refrence_and_move_constructor.cpp">
7272
<Filter>c++11</Filter>
7373
</ClCompile>
74+
<ClCompile Include="constexpr.cpp">
75+
<Filter>c++11</Filter>
76+
</ClCompile>
7477
</ItemGroup>
7578
<ItemGroup>
7679
<ClInclude Include="inc.h">
@@ -156,6 +159,9 @@
156159
<ClInclude Include="rvalue_refrence_and_move_constructor.h">
157160
<Filter>c++11</Filter>
158161
</ClInclude>
162+
<ClInclude Include="constexpr.h">
163+
<Filter>c++11</Filter>
164+
</ClInclude>
159165
</ItemGroup>
160166
<ItemGroup>
161167
<Filter Include="include">

0 commit comments

Comments
 (0)