aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/development
diff options
context:
space:
mode:
authorJohannes Stoelp <johannes.stoelp@gmail.com>2023-04-12 22:41:33 +0200
committerJohannes Stoelp <johannes.stoelp@gmail.com>2023-04-12 22:41:33 +0200
commita6d3ae16736d7746ad6827f10c299ad84aa78a5b (patch)
treeed71c7fb6b2d4cc82c78fd7ec1ffeadadf31c681 /src/development
parent724d077860e103631605f09a7de35e3ad8796f56 (diff)
downloadnotes-a6d3ae16736d7746ad6827f10c299ad84aa78a5b.tar.gz
notes-a6d3ae16736d7746ad6827f10c299ad84aa78a5b.zip
c++: add example for picking template with partial specialzations
Diffstat (limited to 'src/development')
-rw-r--r--src/development/c++.md4
-rw-r--r--src/development/c++/Makefile5
-rw-r--r--src/development/c++/concepts-11.cc3
-rw-r--r--src/development/c++/tmpl-pair.cc73
4 files changed, 82 insertions, 3 deletions
diff --git a/src/development/c++.md b/src/development/c++.md
index e6fcfef..9dc8fb0 100644
--- a/src/development/c++.md
+++ b/src/development/c++.md
@@ -69,6 +69,10 @@ struct is_valid<T, std::void_t<
```
> `std::declval<T>()` creates an instance of type T in an unevaluated context.
+## Template selection with partially / fully specializations.
+```cpp
+{{#include c++/tmpl-pair.cc:3:}}
+```
[gist-strict-asliasing]: https://gist.github.com/shafik/848ae25ee209f698763cffee272a58f8
[parameter-pack]: https://en.cppreference.com/w/cpp/language/parameter_pack
diff --git a/src/development/c++/Makefile b/src/development/c++/Makefile
index 610b5a2..1d5172b 100644
--- a/src/development/c++/Makefile
+++ b/src/development/c++/Makefile
@@ -1,4 +1,4 @@
-SRC = concepts-11.cc meta.cc meta2.cc meta4.cc
+SRC = concepts-11.cc meta.cc meta2.cc meta4.cc tmpl-pair.cc
BIN = $(SRC:.cc=)
all: $(BIN)
@@ -6,5 +6,8 @@ all: $(BIN)
%: %.cc
$(CXX) -o $* $^ -std=c++17 -g -fsanitize=address -fsanitize=undefined -fsanitize=leak
+fmt:
+ clang-format -i $(SRC)
+
clean:
$(RM) $(BIN)
diff --git a/src/development/c++/concepts-11.cc b/src/development/c++/concepts-11.cc
index 888ff4d..cec8716 100644
--- a/src/development/c++/concepts-11.cc
+++ b/src/development/c++/concepts-11.cc
@@ -32,8 +32,7 @@ struct is_entry {
template<typename TT>
using val = decltype(std::declval<TT>().val());
- static constexpr bool value = is_valid_v<T, init> &&
- is_valid_with_ret_v<T, int, tag> &&
+ static constexpr bool value = is_valid_v<T, init> && is_valid_with_ret_v<T, int, tag> &&
is_valid_with_ret_v<T, typename T::Type, val>;
};
diff --git a/src/development/c++/tmpl-pair.cc b/src/development/c++/tmpl-pair.cc
new file mode 100644
index 0000000..a8acaed
--- /dev/null
+++ b/src/development/c++/tmpl-pair.cc
@@ -0,0 +1,73 @@
+// Copyright (C) 2023 johannst
+
+enum Kind {
+ kPrimary,
+ kTT,
+ kIntBool,
+ kIntInt,
+};
+
+// (1) Primary template.
+template<typename T, typename U = bool>
+struct pair {
+ static constexpr Kind kind = kPrimary;
+};
+
+// (2) Partial template specialization.
+template<typename T>
+struct pair<T, T> {
+ static constexpr Kind kind = kTT;
+};
+
+// (3) Template specialization.
+template<>
+struct pair<int, bool> {
+ static constexpr Kind kind = kIntBool;
+};
+
+// (4) Template specialization.
+template<>
+struct pair<int, int> {
+ static constexpr Kind kind = kIntInt;
+};
+
+int main() {
+ static_assert(pair<int>::kind == kIntBool, "");
+ // * Compare template arg list with primary template, we only supplied one
+ // arg, the second one will be defaulted as
+ // pair<int, bool>
+ // * Compare template arg list against available specializations, this will
+ // try to match the pattern <int, bool> against the patterns defined in the
+ // partial specializations.
+ // * (2) <int, bool> pattern does not match
+ // * (3) <int, bool> pattern does match
+ // * (4) <int, bool> pattern does not match
+ // * Pick the most specialized version -> (3)
+
+ static_assert(pair<char, char>::kind == kTT, "");
+ // * Compare template arg list against available specializations, this will
+ // try to match the pattern <char, char> against the patterns defined in the
+ // partial specializations.
+ // * (2) <char, char> pattern does match
+ // * (3) <char, char> pattern does not match
+ // * (4) <char, char> pattern does not match
+ // * Pick the most specialized version -> (2)
+
+ static_assert(pair<int, int>::kind == kIntInt, "");
+ // * Compare template arg list against available specializations, this will
+ // try to match the pattern <int, int> against the patterns defined in the
+ // partial specializations.
+ // * (2) <int, int> pattern does match
+ // * (3) <int, int> pattern does match
+ // * (4) <int, int> pattern does not match
+ // * Pick the most specialized version -> (3)
+
+ static_assert(pair<char, short>::kind == kPrimary, "");
+ // * Compare template arg list against available specializations, this will
+ // try to match the pattern <char, short> against the patterns defined in the
+ // partial specializations.
+ // * (2) <char, short> pattern does not match
+ // * (3) <char, short> pattern does not match
+ // * (4) <char, short> pattern does not match
+ // * No specialization matches, take the primary template.
+}