Skip to content

Commit b09b17a

Browse files
committed
docs: my notes for constexpr
1 parent 86843ea commit b09b17a

File tree

2 files changed

+120
-0
lines changed

2 files changed

+120
-0
lines changed

effective-modern-cpp/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ My learning notes and practice codes for book [Effective Modern C++ (by Scott Me
2020
- [Item 12. Declare overriding functions override](./item-12-declare-overriding-functions-override/)
2121
- [Item 13. Prefer const_iterators to iterators](./item-13-prefer-const_iterators-to-iterators/)
2222
- [Item 14. Declare functions noexcept if they won't emit exceptions](./item-14-declare-functions-noexcept-if-they-wont-emit-exceptions/)
23+
- [Item 15. User constexpr whenever possible](./item-15-use-constexpr-whenever-possible/)
2324

2425
## References
2526
- [Scott Meyers's homepage](https://www.aristeia.com/)
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
# Item 15. User constexpr whenever possible
2+
3+
## Test Codes
4+
5+
- [pow.cc](./pow.cc)
6+
7+
```bash
8+
$ g++ -std=c++11 pow.cc&&./a.out
9+
C++ 201103
10+
pow(3,10)=59049
11+
$
12+
$ g++ -std=c++14 pow.cc&&./a.out
13+
C++ 201402
14+
pow(3,10)=59049
15+
```
16+
17+
- [point.cc](./point.cc)
18+
19+
```bash
20+
$ g++ -std=c++11 point.cc && ./a.out
21+
p1(9.4,27.7)
22+
p2(28.8,5.3)
23+
mid point(19.1,16.5)
24+
$
25+
$ g++ -std=c++14 point.cc && ./a.out
26+
p1(9.4,27.7)
27+
p2(28.8,5.3)
28+
mid point(19.1,16.5)
29+
rp1(-9.4,-27.7)
30+
```
31+
32+
## Notes
33+
Conceptually, `constexpr` indicates a value that's not only constant, it's known during compliation.
34+
35+
### `constexpr` objects
36+
`constexpr` objects are `const`, which have values that are known at compile time(technically compiling or linking).
37+
- Values known during compilation are privileged.
38+
- E.g. they may be placed in read-only memory.
39+
- Of broader applicability is that integral values that are constant and known during compilation can be used in contexts where `C++` requires an **integral constant expression**.
40+
- Such contexts include specification of array sizes, integral template arguments(including lengths of `std::array` objects), enumerator values, alighment specifiers, and more.
41+
42+
```c++
43+
const int sz = 10;
44+
std::array<int, sz> data1; // error! sz's value not known at compilation.
45+
46+
constexpr auto sz2 = 10;
47+
std::array<int, sz2> data2; // fine!
48+
```
49+
50+
- All `constexpr` objects are `const`, but not all `const` objects are `constexpr`.
51+
52+
### `constexpr` functions
53+
`constexpr` functions produce compile-time constants when they're called with compile-time constants. If they're called with values not known until runtime, they produce runtime values.
54+
- The right way to view it:
55+
- `constexpr` functions can be used in context that demand compile-time constants.
56+
- If the values of the arguments you pass to a `constexpr` function in such a context are known during compilation, the result will be computed during compilation.
57+
- If any of the arguments' values is not known during compilation, your code will be rejected.
58+
- When a `constexpr` function is called with one or more values that are not known during compilation, it acts like a normal function, computing its result at runtime.
59+
- This means you don't need two functions to perform the same operation, one for compile-time constants and one for all other values. The `constexpr` function does it all.
60+
- `constexpr` functions implementation restructions
61+
- Because `constexpr` functions must be able to return compile-time results when called with compile-time values, restrictions are imposed on their implementations.
62+
- In `C++11`, `constexpr` functions may contain no more than a single executable statement: a `return`.(`C++14` doesn't have this limitation.) Refer to [pow.cc](./pow.cc) for full code.
63+
64+
```c++
65+
constexpr
66+
int pow(int base, int exp) noexcept {
67+
#if __cplusplus >= 201402L
68+
auto result = 1;
69+
for (int i = 0; i < exp; ++i){
70+
result *= base;
71+
}
72+
return result;
73+
#else
74+
// C++11 requires one single return
75+
return exp <= 0 ? 1 : base * pow(base, exp - 1);
76+
#endif
77+
}
78+
```
79+
80+
- `constexpr` functions are limited to taking and returning literal types, which essentially means types that can have values determined during compilation.
81+
- In `C++11`, all built-in types except `void` qualify, but user-defined types may be literal, too, because constructors and other member functions may be `constexpr`. `C++14` also allows returning `void`.
82+
- In `C++11`, `constexpr` member functions are implicitly `const`. `C++14` doesn't have this convention.
83+
- Refer to [point.cc](./point.cc) for full code.
84+
```c++
85+
class Point{
86+
public:
87+
constexpr Point(double x = 0, double y = 0) noexcept
88+
: x_(x), y_(y) {}
89+
90+
constexpr double x() const noexcept { return x_; }
91+
constexpr double y() const noexcept { return y_; }
92+
93+
#if __cplusplus >= 201402L
94+
constexpr
95+
#endif
96+
void setX(double x) noexcept { x_ = x; }
97+
#if __cplusplus >= 201402L
98+
constexpr
99+
#endif
100+
void setY(double y) noexcept { y_ = y; }
101+
102+
private:
103+
double x_, y_;
104+
};
105+
```
106+
107+
### Conclution
108+
109+
- Both `constexpr` objects and `constexpr` functions can be employed in a wider range of contexts than non-`constexpr` objects and functions.
110+
- By using `constexpr` whenever possible, you maximize the range of situations in which your objects and functions may be used.
111+
- By `constexpr`, the traditionally fairly strict line between work done during compilation and work done at runtime begins to blur.
112+
- Some computations traditionally done at runtime can migrate to compile time.
113+
- The more code taking part in the migration, the faster your software will run.(Compilation may take longer, however.)
114+
- It's important to note that `constexpr` is part of an object's or function's interface.
115+
- `constexpr` proclaims "I can be used in a context where `C++` requires a constant expression."
116+
- Part of "whenever possible" in "Use `constexpr` whenever possible" is your willingness to make a long-term commitment to the constraints it imposes on the objects and functions you apply it to.
117+
118+
## References
119+
- [(Chinese) Understanding C++11 - constexpr](https://github.com/wangyoucao577/modern-cpp/tree/master/understanding-cpp11#constexpr)

0 commit comments

Comments
 (0)