Skip to content

Commit aecdd29

Browse files
committed
Added boilerplate for GitHub repo
1 parent 845ef69 commit aecdd29

10 files changed

+454
-209
lines changed

.gitignore

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
2+
# Created by https://www.gitignore.io/api/emacs,c++
3+
4+
### Emacs ###
5+
# -*- mode: gitignore; -*-
6+
*~
7+
\#*\#
8+
/.emacs.desktop
9+
/.emacs.desktop.lock
10+
*.elc
11+
auto-save-list
12+
tramp
13+
.\#*
14+
15+
# Org-mode
16+
.org-id-locations
17+
*_archive
18+
19+
# flymake-mode
20+
*_flymake.*
21+
22+
# eshell files
23+
/eshell/history
24+
/eshell/lastdir
25+
26+
# elpa packages
27+
/elpa/
28+
29+
# reftex files
30+
*.rel
31+
32+
# AUCTeX auto folder
33+
/auto/
34+
35+
# cask packages
36+
.cask/
37+
dist/
38+
39+
# Flycheck
40+
flycheck_*.el
41+
42+
# server auth directory
43+
/server/
44+
45+
# projectiles files
46+
.projectile
47+
48+
### C++ ###
49+
# Compiled Object files
50+
*.slo
51+
*.lo
52+
*.o
53+
*.obj
54+
55+
# Precompiled Headers
56+
*.gch
57+
*.pch
58+
59+
# Compiled Dynamic libraries
60+
*.so
61+
*.dylib
62+
*.dll
63+
64+
# Fortran module files
65+
*.mod
66+
67+
# Compiled Static libraries
68+
*.lai
69+
*.la
70+
*.a
71+
*.lib
72+
73+
# Executables
74+
*.exe
75+
*.out
76+
*.app
77+

LICENSE

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
The MIT License (MIT)
2+
Copyright (c) 2016 Peter Goldsborough
3+
4+
Permission is hereby granted, free of charge, to any person obtaining a copy of
5+
this software and associated documentation files (the "Software"), to deal in
6+
the Software without restriction, including without limitation the rights to
7+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
8+
the Software, and to permit persons to whom the Software is furnished to do so,
9+
subject to the following conditions:
10+
11+
The above copyright notice and this permission notice shall be included in all
12+
copies or substantial portions of the Software.
13+
14+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
16+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
17+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# C++ Notes
2+
3+
My collection of C++ notes.
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
# Alternatives To Universal References
2+
3+
Overloading a method taking a universal reference can cause problems and
4+
head-aches, as univeral references bind to anything they can. This means that
5+
when you overload such a method and wish to pass a parameter to that overload,
6+
but the parameter does not *quite* fit the declared function parameter, the
7+
univeral reference overload will hit.
8+
9+
```C++
10+
template<typename T>
11+
void print(T&& argument)
12+
{
13+
std::cout << std::forfward<T>(argument);
14+
}
15+
16+
void print(int integer)
17+
{
18+
std::cout << "integer: " << argument;
19+
}
20+
```
21+
22+
Passing a plain integer to the above will work just fine, as overload resolution
23+
will prefer the more specialized `int` overload to the possible (but not chosen)
24+
`int&` overload resulting from the universal reference. However, passing a
25+
`short` will already cause problems. You would expect the `int` overload to be
26+
called, but because `short&` reference is a better match than `int` for a value
27+
of type `short`, the universal reference overload will be picked.
28+
29+
Therefore, it may sometimes be necessary to consider alternatives to overloading
30+
on universal references. These will be presented below.
31+
32+
## Not Overloading
33+
34+
The simplest alternative to overloading on universal references is to not
35+
overload at all, but rename the functions with more specialized names. For
36+
example:
37+
38+
```C++
39+
void print_integer(int integer) { ... }
40+
```
41+
42+
Would no longer cause problems with overload resolution.
43+
44+
Advantages:
45+
+ Solves the problem
46+
+ More expressive (?)
47+
48+
Disadvantage:
49+
- Perfect forwarding lost (would have to overload for all variants of `int`,
50+
`const int&&` etc.)
51+
- Lose the right to use overloads (Human Rights Charta, paragraph 3)
52+
53+
## `const T&`
54+
55+
If the template parameter can be replaced with a concrete type such as
56+
`std::string`, you can replace the universal reference with a `const&` to that
57+
type. Given that a `const&` can bind to lvalues as well as rvalues, passing by
58+
`const&` will reduce the number of types that function will accept.
59+
60+
Advantages:
61+
+ Can use overloading
62+
63+
Disadvantages:
64+
- Lose perfect forwarding
65+
- (Therefore) not as efficient as universal referenes
66+
67+
## Tag Dispatching
68+
69+
As the saying goes: all problems in software engineering can be solved by an
70+
extra level of indirection. We can solve the overload resolution problem by
71+
adding a level of indirection and *dispatching a tag* in dependence of the
72+
parameter passed to the universal reference method. With a *tag* we mean some
73+
trait that differentiates one type from one another. The hidden function then
74+
not only takes the universal reference parameter, but also a tag parameter so
75+
that compile-time overload resolution will kick-in to select the correct
76+
overload. You can see this idea of tag-dispatching as a close alternative to
77+
SFINAE, which is discussed below.
78+
79+
To distinguish between integral and non-integral types for `print`, we can use
80+
the `std::is_integral` type trait on our parameter. For integral types, the
81+
specialized version will inherit from `std::true_type`, so the indirected
82+
overload for integers will take an anonymous `std::true_type` parameter as its
83+
second argument (the `std::is_integral` type will be sliced to
84+
`std::true_type`). For non-integral types, `std::is_integral` will inherit from
85+
`std::false_type`. Therefore, we can write something like this:
86+
87+
```C++
88+
template<typename T>
89+
void print(T&& argument, std::false_type)
90+
{
91+
std::cout << argument;
92+
}
93+
94+
void print(int integer, std::true_type)
95+
{
96+
std::cout << "integer: " << integer;
97+
}
98+
99+
template<typename T>
100+
void print(T&& argument)
101+
{
102+
print(std::forward<T>(argument), std::is_integral<T>{});
103+
}
104+
```
105+
106+
## SFINAE
107+
108+
SFINAE is the go-to solution for restricting the types of parameters template
109+
functions are allowd to accept, and can naturally also be used here. We'll just
110+
have to be sure to remove any (lvalue/rvalue) reference components from the
111+
template type as `int&` is not considered integral (according to
112+
`std::is_integral`) while `int` is. For this we'll use `std::decay`, which
113+
removes all reference components as well as cv-qualifications from a template type.
114+
115+
```C++
116+
template<typename T>
117+
std::enable_if_t<!std::is_same<int, std::decay_t<T>>::value> print(T&& argument)
118+
{
119+
std::cout << argument;
120+
}
121+
122+
void print(int integer)
123+
{
124+
std::cout << "integer: " << integer;
125+
}
126+
```

decay.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# std::decay
2+
3+
`std::decay` is a C++11 type trait that removes all cv-qualifications as well as
4+
refernce components from a template type. I.e. it strips template type `T` of
5+
all non-type components. Moreover, it decays arrays and functions to
6+
pointers. This conversion is precisely the decay that *all* function parameters
7+
passed by value to a function undergo. It is especially useful to compare types,
8+
since `int&` and `int` and `const int` are not the same, for example.
9+
10+
```C++
11+
template<typename T>
12+
std::enable_if_t<std::is_same<int, std::decay_t<T>> f(T&& argument)
13+
{
14+
/* ... */
15+
}
16+
```

0 commit comments

Comments
 (0)