diff options
author | Johannes Stoelp <johannes.stoelp@gmail.com> | 2023-04-12 22:41:33 +0200 |
---|---|---|
committer | Johannes Stoelp <johannes.stoelp@gmail.com> | 2023-04-12 22:41:33 +0200 |
commit | a6d3ae16736d7746ad6827f10c299ad84aa78a5b (patch) | |
tree | ed71c7fb6b2d4cc82c78fd7ec1ffeadadf31c681 | |
parent | 724d077860e103631605f09a7de35e3ad8796f56 (diff) | |
download | notes-a6d3ae16736d7746ad6827f10c299ad84aa78a5b.tar.gz notes-a6d3ae16736d7746ad6827f10c299ad84aa78a5b.zip |
c++: add example for picking template with partial specialzations
-rw-r--r-- | src/development/c++.md | 4 | ||||
-rw-r--r-- | src/development/c++/Makefile | 5 | ||||
-rw-r--r-- | src/development/c++/concepts-11.cc | 3 | ||||
-rw-r--r-- | src/development/c++/tmpl-pair.cc | 73 |
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. +} |