aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--_includes/snippets/footer.html5
-rw-r--r--_includes/snippets/header.html14
-rw-r--r--_includes/snippets/section.html25
-rw-r--r--_posts/2017-06-24-static-vs-inline-vs-unnamed-namespaces.md277
-rw-r--r--_posts/snippets/static_vs_inline_vs_unnamed_namespaces/inline/shared.hpp7
-rw-r--r--_posts/snippets/static_vs_inline_vs_unnamed_namespaces/inline/weird/another.cpp13
-rw-r--r--_posts/snippets/static_vs_inline_vs_unnamed_namespaces/inline/weird/another.hpp3
-rw-r--r--_posts/snippets/static_vs_inline_vs_unnamed_namespaces/inline/weird/main.cpp15
-rw-r--r--_posts/snippets/static_vs_inline_vs_unnamed_namespaces/separate_method_definitions/another.cpp7
-rw-r--r--_posts/snippets/static_vs_inline_vs_unnamed_namespaces/separate_method_definitions/another.hpp3
-rw-r--r--_posts/snippets/static_vs_inline_vs_unnamed_namespaces/separate_method_definitions/main.cpp9
-rw-r--r--_posts/snippets/static_vs_inline_vs_unnamed_namespaces/separate_method_definitions/shared.hpp14
-rw-r--r--_posts/snippets/static_vs_inline_vs_unnamed_namespaces/static/main.cpp11
-rw-r--r--_posts/snippets/static_vs_inline_vs_unnamed_namespaces/static/proxy.cpp7
-rw-r--r--_posts/snippets/static_vs_inline_vs_unnamed_namespaces/static/proxy.hpp3
-rw-r--r--_posts/snippets/static_vs_inline_vs_unnamed_namespaces/static/shared.hpp7
-rw-r--r--_posts/snippets/static_vs_inline_vs_unnamed_namespaces/static_and_inline/main.cpp11
-rw-r--r--_posts/snippets/static_vs_inline_vs_unnamed_namespaces/static_and_inline/proxy.cpp7
-rw-r--r--_posts/snippets/static_vs_inline_vs_unnamed_namespaces/static_and_inline/proxy.hpp3
-rw-r--r--_posts/snippets/static_vs_inline_vs_unnamed_namespaces/static_and_inline/shared.hpp7
-rw-r--r--_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespace_and_inline/main.cpp11
-rw-r--r--_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespace_and_inline/proxy.cpp7
-rw-r--r--_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespace_and_inline/proxy.hpp3
-rw-r--r--_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespace_and_inline/shared.hpp10
-rw-r--r--_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespaces/ok/another.cpp18
-rw-r--r--_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespaces/ok/another.hpp3
-rw-r--r--_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespaces/ok/main.cpp21
-rw-r--r--_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespaces/weird/another.cpp15
-rw-r--r--_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespaces/weird/another.hpp3
-rw-r--r--_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespaces/weird/main.cpp18
-rw-r--r--css/snippets.css9
31 files changed, 566 insertions, 0 deletions
diff --git a/_includes/snippets/footer.html b/_includes/snippets/footer.html
new file mode 100644
index 0000000..d60469c
--- /dev/null
+++ b/_includes/snippets/footer.html
@@ -0,0 +1,5 @@
+ </div>
+ {% if page.snippets_collapsible %}
+ </div>
+ {% endif %}
+</div>
diff --git a/_includes/snippets/header.html b/_includes/snippets/header.html
new file mode 100644
index 0000000..673fc5a
--- /dev/null
+++ b/_includes/snippets/header.html
@@ -0,0 +1,14 @@
+{% capture snippet_basename %}{{ include.snippet_path | split:"/" | last }}{% endcapture %}
+{% capture snippet_id %}{{ include.snippet_path | replace:'/','_' | replace:'.','_' }}{% endcapture %}
+<div class="panel panel-default">
+ <div class="panel-heading">
+ {% if page.snippets_collapsible %}
+ <a id="{{ snippet_id }}" data-toggle="collapse" data-parent="#accordion_{{ include.section_id }}" href="#collapse_{{ snippet_id }}">{{ snippet_basename }}</a>
+ {% else %}
+ <div id="{{ snippet_id }}">{{ snippet_basename }}</div>
+ {% endif %}
+ </div>
+ {% if page.snippets_collapsible %}
+ <div id="collapse_{{ snippet_id }}" class="panel-collapse collapse">
+ {% endif %}
+ <div class="panel-body">
diff --git a/_includes/snippets/section.html b/_includes/snippets/section.html
new file mode 100644
index 0000000..79be3c1
--- /dev/null
+++ b/_includes/snippets/section.html
@@ -0,0 +1,25 @@
+{% if page.snippets_collapsible %}
+<div class="panel-group" id="accordion_{{ include.section_id }}">
+{% else %}
+<div class="panel-group">
+{% endif %}
+
+{% for i in page.snippets[include.section_id] %}
+ {% include snippets/header.html snippet_path=i section_id=include.section_id %}
+
+{% capture snippet %}
+```c++
+{% include_relative {{ page.snippets_root_directory }}/{{ i }} %}```
+{% endcapture %}
+
+{{ snippet | markdownify }}
+
+ {% include snippets/footer.html %}
+{% endfor %}
+
+</div>
+
+{% for i in page.snippets[include.section_id] %}
+ {% capture snippet_id %}{{ i | replace:"/","_" | replace:".","_" }}{% endcapture %}
+[{{ i }}]: #{{ snippet_id }}
+{% endfor %}
diff --git a/_posts/2017-06-24-static-vs-inline-vs-unnamed-namespaces.md b/_posts/2017-06-24-static-vs-inline-vs-unnamed-namespaces.md
new file mode 100644
index 0000000..e22ab21
--- /dev/null
+++ b/_posts/2017-06-24-static-vs-inline-vs-unnamed-namespaces.md
@@ -0,0 +1,277 @@
+---
+title: static vs. inline vs. namespace {
+layout: post
+excerpt: >
+ Should I use <code>static</code>, <code>inline</code> or unnamed namespaces
+ for function definitions?
+custom_css:
+ - snippets.css
+snippets_root_directory: snippets/static_vs_inline_vs_unnamed_namespaces/
+snippets:
+ static:
+ - static/main.cpp
+ - static/proxy.cpp
+ - static/proxy.hpp
+ - static/shared.hpp
+ inline:
+ - inline/shared.hpp
+ inline_weird:
+ - inline/weird/main.cpp
+ - inline/weird/another.cpp
+ - inline/weird/another.hpp
+ unnamed_namespaces_weird:
+ - unnamed_namespaces/weird/main.cpp
+ - unnamed_namespaces/weird/another.cpp
+ - unnamed_namespaces/weird/another.hpp
+ unnamed_namespaces_ok:
+ - unnamed_namespaces/ok/main.cpp
+ - unnamed_namespaces/ok/another.cpp
+ - unnamed_namespaces/ok/another.hpp
+ static_and_inline:
+ - static_and_inline/main.cpp
+ - static_and_inline/proxy.cpp
+ - static_and_inline/proxy.hpp
+ - static_and_inline/shared.hpp
+ unnamed_namespace_and_inline:
+ - unnamed_namespace_and_inline/main.cpp
+ - unnamed_namespace_and_inline/proxy.cpp
+ - unnamed_namespace_and_inline/proxy.hpp
+ - unnamed_namespace_and_inline/shared.hpp
+ separate_method_definitions:
+ - separate_method_definitions/main.cpp
+ - separate_method_definitions/another.cpp
+ - separate_method_definitions/another.hpp
+ - separate_method_definitions/shared.hpp
+---
+In this post I'll try to figure out whether I should use `static`, `inline` or
+unnamed namespaces for function definitions.
+
+`static`
+--------
+
+It's an old C-style method of defining functions in header files.
+This way, every translation unit gets its own copy of a function.
+What does that mean?
+The most obvious implication that pops into my head is that every local static
+variable defined inside that function gets an independent replica in every
+translation unit.
+For example, the program below would print
+
+```
+1
+1
+```
+
+due to the fact that both main.cpp and proxy.cpp get their own versions of `n`
+from `shared()`.
+
+{% include snippets/section.html section_id='static' %}
+
+In C, this is the only way to share function definitions between translation
+units (apart from declaring a function in a header file and putting its
+definition to a .c file).
+
+### Properties
+
+* Using `static`, you can share function definitions between multiple
+translation units.
+* Each unit gets its own replica of the function: they have different
+addresses, their local static variables are independent, etc.
+* If different translation units define different functions with the same
+name using the `static` specifier, each unit can use its function without any
+issues.
+This might seem like an trivial claim, but there are issues with other
+approaches that are discussed below.
+
+`inline`
+--------
+
+It's well-known that this keyword has pretty much nothing to do with whether a
+function will actually be inlined or not.
+It's used much more often to define functions in header files, since every
+function defined this way will be the same (as in "will have the same address")
+in every translation unit.
+Let's try and adjust the definition of `shared()` accordingly:
+
+{% include snippets/section.html section_id='inline' %}
+
+The same program would then print
+
+```
+1
+2
+```
+
+since both `main()` and `proxy()` would call the same `shared()`, incrementing
+the same `n`.
+
+Weird things happen when different translation units define different `inline`
+functions with the same name.
+
+{% include snippets/section.html section_id='inline_weird' %}
+
+According to my simple experiments, this program produces different output
+based on which .cpp file was specified first on the command line during
+compilation.
+For example, this is the output of test.exe produced with either `cl /W4 /EHsc
+main.cpp another.cpp /Fe:test.exe` or `g++ -Wall -Wextra -std=c++11 main.cpp
+another.cpp -o test.exe`.
+
+```
+main.cpp: shared()
+main.cpp: shared()
+```
+
+If we swap the order of .cpp files (`another.cpp main.cpp` instead of `main.cpp
+another.cpp`), the output becomes
+
+```
+another.cpp: shared()
+another.cpp: shared()
+```
+
+No warnings/errors are emitted, making the situation truly disturbing.
+I tested this with GNU compiler version 5.4.0 and Microsoft compiler version
+19.00.24210.
+
+This behaviour can be easily fixed by either making these functions `static`
+or by using unnamed namespaces (see below).
+
+### Properties
+
+* Using `inline`, you can share function definitions between multiple
+translation units.
+* Each translation unit will use the same function: it will have the same
+address in every translation unit, its local static variables will be shared,
+etc.
+* Defining different `inline` functions with the same name in different
+translation units is undefined behaviour.
+
+Two inline functions might be different even if they are the same textually.
+For example, they might reference two global variables which have the same
+name, but are defined in different translation units.
+{: .alert .alert-info }
+
+`namespace {`
+-------------
+
+With respect to function definitions, unnamed namespaces are, according to my
+understanding, quite similar to the `static` keyword.
+The additional value they provide is that they provide a way to apply `static`
+not only to functions, but to classes also.
+Remember the weirdness that happens when multiple translation units define
+different `inline` functions with the same name?
+Arguably, it gets even worse if we add classes to the equation.
+
+{% include snippets/section.html section_id='unnamed_namespaces_weird' %}
+
+Compiling this program the same way we did in the `inline` example (`cl /W4
+/EHsc main.cpp another.cpp /Fe:test.exe`/`g++ -Wall -Wextra -std=c++11 main.cpp
+another.cpp -o test.exe`) yields different outputs depending on which .cpp file
+was specified first.
+
+```
+main.cpp: Test::Test()
+1
+main.cpp: Test::Test()
+```
+
+```
+another.cpp: Test::Test()
+1065353216
+another.cpp: Test::Test()
+```
+
+I'm not sure why anybody would want that.
+This can be easily fixed by putting both `Test` classes into unnamed
+namespaces.
+The program than reads
+
+{% include snippets/section.html section_id='unnamed_namespaces_ok' %}
+
+After the adjustment, it produces the same output regardless of compilation
+options.
+
+```
+main.cpp: Test::Test()
+1
+another.cpp: Test::Test()
+```
+
+Notice how sharing classes defined in header files isn't discussed here.
+The standard actually guarantees that if a class is defined in a header file,
+all translation units that use it share the definition.
+
+### Properties
+
+* Essentially, unnamed namespaces allow the `static` keyword to be applied to
+classes.
+* Similar to the `static` approach, each translation unit gets its own replica
+of a function/class, including their own local static variables, etc.
+* Defining different classes with the same name in different translation units
+(without utilizing unnamed namespaces) is undefined behaviour.
+
+Conclusion
+----------
+
+Here's my attempt to build an algorithm to decide whether a class/function
+should be defined with either of the `static`/`inline` specifiers or put into
+an unnamed namespace.
+The first question I answer is: is the entity defined in a header file or in a
+.cpp file?
+
+* **In a header** &mdash; Is it a class or a function?
+ * **Class** &mdash; There's no need to do anything.
+ * **Function** &mdash; Do you want it to behave differently for each
+translation unit (may be useful, for example, for logging)?
+ * **Yes** &mdash; Use `static`.
+ * **No** &mdash; Use `inline`.
+* **In a .cpp file** &mdash; Put it into an unnamed namespace.
+
+Tricky cases
+------------
+
+### `static` + `inline`
+
+In case a function is defined as `static inline`, `static` wins, and `inline`
+is ignored.
+The program below outputs
+
+```
+1
+1
+```
+
+{% include snippets/section.html section_id='static_and_inline' %}
+
+In general, I can't think of a reason to define a `static inline` function.
+
+### `namespace {` + `inline`
+
+If an `inline` function is defined in an unnamed namespace, the unnamed
+namespace wins.
+The program below outputs
+
+```
+1
+1
+```
+
+{% include snippets/section.html section_id='unnamed_namespace_and_inline' %}
+
+In general, I can't think of a reason to define an `inline` function in an
+unnamed namespace.
+
+### Separate method definitions
+
+If you want to separate your class declaration from its method definitions
+while keeping them in the same header file, each method must be explicitly
+defined `inline`.
+The program below outputs
+
+```
+1
+2
+```
+
+{% include snippets/section.html section_id='separate_method_definitions' %}
diff --git a/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/inline/shared.hpp b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/inline/shared.hpp
new file mode 100644
index 0000000..91313f2
--- /dev/null
+++ b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/inline/shared.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+inline int shared()
+{
+ static int n = 0;
+ return ++n;
+}
diff --git a/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/inline/weird/another.cpp b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/inline/weird/another.cpp
new file mode 100644
index 0000000..668516a
--- /dev/null
+++ b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/inline/weird/another.cpp
@@ -0,0 +1,13 @@
+#include "another.hpp"
+
+#include <iostream>
+
+inline void shared()
+{
+ std::cout << "another.cpp: shared()\n";
+}
+
+void another()
+{
+ shared();
+}
diff --git a/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/inline/weird/another.hpp b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/inline/weird/another.hpp
new file mode 100644
index 0000000..9c26d3f
--- /dev/null
+++ b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/inline/weird/another.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+void another();
diff --git a/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/inline/weird/main.cpp b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/inline/weird/main.cpp
new file mode 100644
index 0000000..4e32fb5
--- /dev/null
+++ b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/inline/weird/main.cpp
@@ -0,0 +1,15 @@
+#include "another.hpp"
+
+#include <iostream>
+
+inline void shared()
+{
+ std::cout << "main.cpp: shared()\n";
+}
+
+int main()
+{
+ shared();
+ another();
+ return 0;
+}
diff --git a/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/separate_method_definitions/another.cpp b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/separate_method_definitions/another.cpp
new file mode 100644
index 0000000..d8d53ae
--- /dev/null
+++ b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/separate_method_definitions/another.cpp
@@ -0,0 +1,7 @@
+#include "another.hpp"
+#include "shared.hpp"
+
+void another()
+{
+ Test test;
+}
diff --git a/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/separate_method_definitions/another.hpp b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/separate_method_definitions/another.hpp
new file mode 100644
index 0000000..9c26d3f
--- /dev/null
+++ b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/separate_method_definitions/another.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+void another();
diff --git a/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/separate_method_definitions/main.cpp b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/separate_method_definitions/main.cpp
new file mode 100644
index 0000000..8d2043f
--- /dev/null
+++ b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/separate_method_definitions/main.cpp
@@ -0,0 +1,9 @@
+#include "another.hpp"
+#include "shared.hpp"
+
+int main()
+{
+ Test test;
+ another();
+ return 0;
+}
diff --git a/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/separate_method_definitions/shared.hpp b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/separate_method_definitions/shared.hpp
new file mode 100644
index 0000000..ef2d525
--- /dev/null
+++ b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/separate_method_definitions/shared.hpp
@@ -0,0 +1,14 @@
+#pragma once
+
+#include <iostream>
+
+struct Test
+{
+ Test();
+};
+
+inline Test::Test()
+{
+ static int x = 0;
+ std::cout << ++x << '\n';
+}
diff --git a/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/static/main.cpp b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/static/main.cpp
new file mode 100644
index 0000000..7fbeb56
--- /dev/null
+++ b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/static/main.cpp
@@ -0,0 +1,11 @@
+#include "proxy.hpp"
+#include "shared.hpp"
+
+#include <iostream>
+
+int main()
+{
+ std::cout << shared() << '\n';
+ std::cout << proxy() << '\n';
+ return 0;
+}
diff --git a/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/static/proxy.cpp b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/static/proxy.cpp
new file mode 100644
index 0000000..a8eef26
--- /dev/null
+++ b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/static/proxy.cpp
@@ -0,0 +1,7 @@
+#include "proxy.hpp"
+#include "shared.hpp"
+
+int proxy()
+{
+ return shared();
+}
diff --git a/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/static/proxy.hpp b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/static/proxy.hpp
new file mode 100644
index 0000000..7dfc52a
--- /dev/null
+++ b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/static/proxy.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+int proxy();
diff --git a/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/static/shared.hpp b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/static/shared.hpp
new file mode 100644
index 0000000..6f812ab
--- /dev/null
+++ b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/static/shared.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+static int shared()
+{
+ static int n = 0;
+ return ++n;
+}
diff --git a/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/static_and_inline/main.cpp b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/static_and_inline/main.cpp
new file mode 100644
index 0000000..7fbeb56
--- /dev/null
+++ b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/static_and_inline/main.cpp
@@ -0,0 +1,11 @@
+#include "proxy.hpp"
+#include "shared.hpp"
+
+#include <iostream>
+
+int main()
+{
+ std::cout << shared() << '\n';
+ std::cout << proxy() << '\n';
+ return 0;
+}
diff --git a/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/static_and_inline/proxy.cpp b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/static_and_inline/proxy.cpp
new file mode 100644
index 0000000..a8eef26
--- /dev/null
+++ b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/static_and_inline/proxy.cpp
@@ -0,0 +1,7 @@
+#include "proxy.hpp"
+#include "shared.hpp"
+
+int proxy()
+{
+ return shared();
+}
diff --git a/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/static_and_inline/proxy.hpp b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/static_and_inline/proxy.hpp
new file mode 100644
index 0000000..7dfc52a
--- /dev/null
+++ b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/static_and_inline/proxy.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+int proxy();
diff --git a/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/static_and_inline/shared.hpp b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/static_and_inline/shared.hpp
new file mode 100644
index 0000000..a669247
--- /dev/null
+++ b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/static_and_inline/shared.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+static inline int shared()
+{
+ static int x = 0;
+ return ++x;
+}
diff --git a/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespace_and_inline/main.cpp b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespace_and_inline/main.cpp
new file mode 100644
index 0000000..7fbeb56
--- /dev/null
+++ b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespace_and_inline/main.cpp
@@ -0,0 +1,11 @@
+#include "proxy.hpp"
+#include "shared.hpp"
+
+#include <iostream>
+
+int main()
+{
+ std::cout << shared() << '\n';
+ std::cout << proxy() << '\n';
+ return 0;
+}
diff --git a/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespace_and_inline/proxy.cpp b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespace_and_inline/proxy.cpp
new file mode 100644
index 0000000..a8eef26
--- /dev/null
+++ b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespace_and_inline/proxy.cpp
@@ -0,0 +1,7 @@
+#include "proxy.hpp"
+#include "shared.hpp"
+
+int proxy()
+{
+ return shared();
+}
diff --git a/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespace_and_inline/proxy.hpp b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespace_and_inline/proxy.hpp
new file mode 100644
index 0000000..7dfc52a
--- /dev/null
+++ b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespace_and_inline/proxy.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+int proxy();
diff --git a/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespace_and_inline/shared.hpp b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespace_and_inline/shared.hpp
new file mode 100644
index 0000000..c64cc41
--- /dev/null
+++ b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespace_and_inline/shared.hpp
@@ -0,0 +1,10 @@
+#pragma once
+
+namespace
+{
+ inline int shared()
+ {
+ static int x = 0;
+ return ++x;
+ }
+}
diff --git a/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespaces/ok/another.cpp b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespaces/ok/another.cpp
new file mode 100644
index 0000000..10128ef
--- /dev/null
+++ b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespaces/ok/another.cpp
@@ -0,0 +1,18 @@
+#include "another.hpp"
+
+#include <iostream>
+
+namespace
+{
+ struct Test
+ {
+ Test() { std::cout << "another.cpp: Test::Test()\n"; }
+
+ float y = 1.;
+ };
+}
+
+void another()
+{
+ Test test;
+}
diff --git a/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespaces/ok/another.hpp b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespaces/ok/another.hpp
new file mode 100644
index 0000000..9c26d3f
--- /dev/null
+++ b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespaces/ok/another.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+void another();
diff --git a/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespaces/ok/main.cpp b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespaces/ok/main.cpp
new file mode 100644
index 0000000..c0c0664
--- /dev/null
+++ b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespaces/ok/main.cpp
@@ -0,0 +1,21 @@
+#include "another.hpp"
+
+#include <iostream>
+
+namespace
+{
+ struct Test
+ {
+ Test() { std::cout << "main.cpp: Test::Test()\n"; }
+
+ int x = 1;
+ };
+}
+
+int main()
+{
+ Test test;
+ std::cout << test.x << '\n';
+ another();
+ return 0;
+}
diff --git a/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespaces/weird/another.cpp b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespaces/weird/another.cpp
new file mode 100644
index 0000000..8a125ec
--- /dev/null
+++ b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespaces/weird/another.cpp
@@ -0,0 +1,15 @@
+#include "another.hpp"
+
+#include <iostream>
+
+struct Test
+{
+ Test() { std::cout << "another.cpp: Test::Test()\n"; }
+
+ float y = 1.;
+};
+
+void another()
+{
+ Test test;
+}
diff --git a/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespaces/weird/another.hpp b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespaces/weird/another.hpp
new file mode 100644
index 0000000..9c26d3f
--- /dev/null
+++ b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespaces/weird/another.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+void another();
diff --git a/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespaces/weird/main.cpp b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespaces/weird/main.cpp
new file mode 100644
index 0000000..8ab8fb8
--- /dev/null
+++ b/_posts/snippets/static_vs_inline_vs_unnamed_namespaces/unnamed_namespaces/weird/main.cpp
@@ -0,0 +1,18 @@
+#include "another.hpp"
+
+#include <iostream>
+
+struct Test
+{
+ Test() { std::cout << "main.cpp: Test::Test()\n"; }
+
+ int x = 1;
+};
+
+int main()
+{
+ Test test;
+ std::cout << test.x << '\n';
+ another();
+ return 0;
+}
diff --git a/css/snippets.css b/css/snippets.css
new file mode 100644
index 0000000..5294e00
--- /dev/null
+++ b/css/snippets.css
@@ -0,0 +1,9 @@
+div.panel-body pre {
+ margin: 0;
+ border: none;
+ background-color: inherit;
+ border-radius: 0 0 4px 4px;
+}
+div.panel-body {
+ padding: 0;
+}