diff options
Diffstat (limited to 'development/c++.html')
-rw-r--r-- | development/c++.html | 129 |
1 files changed, 121 insertions, 8 deletions
diff --git a/development/c++.html b/development/c++.html index c8ed843..811aa7d 100644 --- a/development/c++.html +++ b/development/c++.html @@ -32,6 +32,7 @@ </head> <body> + <div id="body-container"> <!-- Provide site root to javascript --> <script> var path_to_root = "../"; @@ -69,10 +70,12 @@ <!-- Hide / unhide sidebar before it is displayed --> <script> var html = document.querySelector('html'); - var sidebar = 'hidden'; + var sidebar = null; if (document.body.clientWidth >= 1080) { try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { } sidebar = sidebar || 'visible'; + } else { + sidebar = 'hidden'; } html.classList.remove('sidebar-visible'); html.classList.add("sidebar-" + sidebar); @@ -446,8 +449,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>; }; @@ -470,18 +472,128 @@ int main() { of the <code>decltype(std:declval<T>...</code> expressions is ill-formed, the template specialization for <code>is_valid</code> will be removed from the candidate set due to <a href="https://en.cppreference.com/w/cpp/language/sfinae">SFINAE</a>.</p> -<pre><code class="language-cpp">template<typename T, typename = void> +<pre><code class="language-cpp">#include <type_traits> + +// (1) Primary template. +template<typename T, typename = void> struct is_valid : std::false_type {}; +// (2) Partial template specialization. template<typename T> -struct is_valid<T, std::void_t< - decltype(std::declval<T>().some_fun1()), - decltype(std::declval<T>().some_fun2()) - >> : std::true_type {}; +struct is_valid<T, std::void_t<decltype(std::declval<T>().some_fun1()), + decltype(std::declval<T>().some_fun2())>> : std::true_type {}; +struct A { + void some_fun1() {} + void some_fun2() {} +}; + +struct B {}; + +static_assert(is_valid<A>::value, "is true"); +// * Compare template arg list with primary template, we only supplied one +// arg, the second one will be defaulted as +// is_valid<A, void> +// * Compare template arg list against available specializations, this will +// try to match the pattern <A, void> against the patterns defined in the +// partial specializations. +// * Try specialization (2) +// * T -> A +// * Evaluate std::void_t -> decltype's are well-formed +// std::void_t<...> -> void +// * Specialization (2) matches <A, void> +// * Pick the most specialized version -> (2) + +static_assert(!is_valid<B>::value, "is false"); +// * Compare template arg list with primary template, we only supplied one +// arg, the second one will be defaulted as +// is_valid<A, void> +// * Compare template arg list against available specializations, this will +// try to match the pattern <B, void> against the patterns defined in the +// partial specializations. +// * Try specialization (2) +// * T -> B +// * Evaluate std::void_t -> decltype's are ill-formed +// * Specialization (2) is removed from candidate set, no hard error (SFINAE) +// * No specialization matches, take the primary template. </code></pre> <blockquote> <p><code>std::declval<T>()</code> creates an instance of type T in an unevaluated context.</p> </blockquote> +<p>A more detailed description is available in the SO discussion <a href="https://stackoverflow.com/a/27688405">How does +<code>void_t</code> work</a>.</p> +<h2 id="template-selection-with-partially--fully-specializations"><a class="header" href="#template-selection-with-partially--fully-specializations">Template selection with partially / fully specializations.</a></h2> +<pre><code class="language-cpp">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. +} +</code></pre> </main> @@ -531,5 +643,6 @@ struct is_valid<T, std::void_t< <!-- Custom JS scripts --> + </div> </body> </html> |