{"id":6257,"date":"2021-12-03T13:34:13","date_gmt":"2021-12-03T13:34:13","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/the-type-traits-library-std-is-base-of\/"},"modified":"2023-06-26T09:21:30","modified_gmt":"2023-06-26T09:21:30","slug":"the-type-traits-library-std-is-base-of","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/the-type-traits-library-std-is-base-of\/","title":{"rendered":"The Type-Traits Library: std::is_base_of"},"content":{"rendered":"<p>I finished the last article on the Type-Traits library with the challenge of explaining the <code>std::is_base_of<\/code> and<code> std::is_convertible<\/code> functions. Today I&#8217;m excited to present the answer from Mr. Helmut Zeisel.<\/p>\n<p><!--more--><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6251\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/11\/templatesTypeTraits.png\" alt=\"templatesTypeTraits\" width=\"650\" height=\"412\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/11\/templatesTypeTraits.png 918w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/11\/templatesTypeTraits-300x190.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2021\/11\/templatesTypeTraits-768x487.png 768w\" sizes=\"auto, (max-width: 650px) 100vw, 650px\" \/><\/p>\n<p>Before I present Mr. Zeisel&#8217;s response, I would like to repeat the challenge briefly.<\/p>\n<h2>My challenge<\/h2>\n<p>Explain the two implementations of the type-traits functions<code> std::is_base_o<\/code>f and <code>std::is_convertible<\/code>.<\/p>\n<ul>\n<li><code>std::is_base_of<\/code>\n<ul><!-- HTML generated using hilite.me --><\/ul>\n<\/li>\n<\/ul>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #006699; font-weight: bold;\">namespace<\/span> details {\r\n    <span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> B<span style=\"color: #555555;\">&gt;<\/span>\r\n    std<span style=\"color: #555555;\">::<\/span>true_type test_pre_ptr_convertible(<span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #006699; font-weight: bold;\">volatile<\/span> B<span style=\"color: #555555;\">*<\/span>);\r\n    <span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span><span style=\"color: #555555;\">&gt;<\/span>\r\n    std<span style=\"color: #555555;\">::<\/span>false_type test_pre_ptr_convertible(<span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #006699; font-weight: bold;\">volatile<\/span> <span style=\"color: #007788; font-weight: bold;\">void<\/span><span style=\"color: #555555;\">*<\/span>);\r\n \r\n    <span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span>, <span style=\"color: #006699; font-weight: bold;\">typename<\/span><span style=\"color: #555555;\">&gt;<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">auto<\/span> test_pre_is_base_of(...) <span style=\"color: #555555;\">-&gt;<\/span> std<span style=\"color: #555555;\">::<\/span>true_type;\r\n    <span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> B, <span style=\"color: #006699; font-weight: bold;\">typename<\/span> D<span style=\"color: #555555;\">&gt;<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">auto<\/span> test_pre_is_base_of(<span style=\"color: #007788; font-weight: bold;\">int<\/span>) <span style=\"color: #555555;\">-&gt;<\/span>\r\n        decltype(test_pre_ptr_convertible<span style=\"color: #555555;\">&lt;<\/span>B<span style=\"color: #555555;\">&gt;<\/span>(<span style=\"color: #006699; font-weight: bold;\">static_cast<\/span><span style=\"color: #555555;\">&lt;<\/span>D<span style=\"color: #555555;\">*&gt;<\/span>(nullptr)));\r\n}\r\n \r\n<span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> Base, <span style=\"color: #006699; font-weight: bold;\">typename<\/span> Derived<span style=\"color: #555555;\">&gt;<\/span>\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> is_base_of <span style=\"color: #555555;\">:<\/span>\r\n    std<span style=\"color: #555555;\">::<\/span>integral_constant<span style=\"color: #555555;\">&lt;<\/span>\r\n        boolean,\r\n        std<span style=\"color: #555555;\">::<\/span>is_class<span style=\"color: #555555;\">&lt;<\/span>Base<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&amp;&amp;<\/span> std<span style=\"color: #555555;\">::<\/span>is_class<span style=\"color: #555555;\">&lt;<\/span>Derived<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&amp;&amp;<\/span>\r\n        decltype(details<span style=\"color: #555555;\">::<\/span>test_pre_is_base_of<span style=\"color: #555555;\">&lt;<\/span>Base, Derived<span style=\"color: #555555;\">&gt;<\/span>(<span style=\"color: #ff6600;\">0<\/span>))<span style=\"color: #555555;\">::<\/span>value\r\n    <span style=\"color: #555555;\">&gt;<\/span> { };\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<ul>\n<ul>\n<li><code>std::is_convertible<\/code><\/li>\n<p><!-- HTML generated using hilite.me --><\/ul>\n<\/ul>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #006699; font-weight: bold;\">namespace<\/span> detail {\r\n \r\n<span style=\"color: #006699; font-weight: bold;\">template<\/span><span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">T<\/span><span style=\"color: #555555;\">&gt;<\/span>\r\n<span style=\"color: #006699; font-weight: bold;\">auto<\/span> test_returnable(<span style=\"color: #007788; font-weight: bold;\">int<\/span>) <span style=\"color: #555555;\">-&gt;<\/span> decltype(\r\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span>(<span style=\"color: #006699; font-weight: bold;\">static_cast<\/span><span style=\"color: #555555;\">&lt;<\/span>T(<span style=\"color: #555555;\">*<\/span>)()<span style=\"color: #555555;\">&gt;<\/span>(nullptr)), std<span style=\"color: #555555;\">::<\/span>true_type{}\r\n);\r\n<span style=\"color: #006699; font-weight: bold;\">template<\/span><span style=\"color: #555555;\">&lt;<\/span>class<span style=\"color: #555555;\">&gt;<\/span>\r\n<span style=\"color: #006699; font-weight: bold;\">auto<\/span> test_returnable(...) <span style=\"color: #555555;\">-&gt;<\/span> std<span style=\"color: #555555;\">::<\/span>false_type;\r\n \r\n<span style=\"color: #006699; font-weight: bold;\">template<\/span><span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">From<\/span>, <span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">To<\/span><span style=\"color: #555555;\">&gt;<\/span>\r\n<span style=\"color: #006699; font-weight: bold;\">auto<\/span> test_implicitly_convertible(<span style=\"color: #007788; font-weight: bold;\">int<\/span>) <span style=\"color: #555555;\">-&gt;<\/span> decltype(\r\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span>(std<span style=\"color: #555555;\">::<\/span>declval<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">void<\/span>(<span style=\"color: #555555;\">&amp;<\/span>)(To)<span style=\"color: #555555;\">&gt;<\/span>()(std<span style=\"color: #555555;\">::<\/span>declval<span style=\"color: #555555;\">&lt;<\/span>From<span style=\"color: #555555;\">&gt;<\/span>())), std<span style=\"color: #555555;\">::<\/span>true_type{}\r\n);\r\n<span style=\"color: #006699; font-weight: bold;\">template<\/span><span style=\"color: #555555;\">&lt;<\/span>class, class<span style=\"color: #555555;\">&gt;<\/span>\r\n<span style=\"color: #006699; font-weight: bold;\">auto<\/span> test_implicitly_convertible(...) <span style=\"color: #555555;\">-&gt;<\/span> std<span style=\"color: #555555;\">::<\/span>false_type;\r\n \r\n} <span style=\"color: #0099ff; font-style: italic;\">\/\/ namespace detail<\/span>\r\n \r\n<span style=\"color: #006699; font-weight: bold;\">template<\/span><span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">From<\/span>, <span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">To<\/span><span style=\"color: #555555;\">&gt;<\/span>\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> is_convertible <span style=\"color: #555555;\">:<\/span> std<span style=\"color: #555555;\">::<\/span>integral_constant<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">bool<\/span>,\r\n    (decltype(detail<span style=\"color: #555555;\">::<\/span>test_returnable<span style=\"color: #555555;\">&lt;<\/span>To<span style=\"color: #555555;\">&gt;<\/span>(<span style=\"color: #ff6600;\">0<\/span>))<span style=\"color: #555555;\">::<\/span>value <span style=\"color: #555555;\">&amp;&amp;<\/span>\r\n     decltype(detail<span style=\"color: #555555;\">::<\/span>test_implicitly_convertible<span style=\"color: #555555;\">&lt;<\/span>From, To<span style=\"color: #555555;\">&gt;<\/span>(<span style=\"color: #ff6600;\">0<\/span>))<span style=\"color: #555555;\">::<\/span>value) <span style=\"color: #555555;\">||<\/span>\r\n    (std<span style=\"color: #555555;\">::<\/span>is_void<span style=\"color: #555555;\">&lt;<\/span>From<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&amp;&amp;<\/span> std<span style=\"color: #555555;\">::<\/span>is_void<span style=\"color: #555555;\">&lt;<\/span>To<span style=\"color: #555555;\">&gt;::<\/span>value)\r\n<span style=\"color: #555555;\">&gt;<\/span> {};\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Admittedly, there are significantly simpler challenges. Therefore, I only got one perfect answer to <code>std::is_base_of<\/code>. However, it is worth studying the following explanation by Mr. Zeisel, as it is very instructive. I translated his German explanation into English, and I kept his layout.<\/p>\n<\/p>\n<h2><code>std::is_base_of<\/code><\/h2>\n<h3>Program1.cpp<\/h3>\n<p><code>std::is_base_of<\/code> is essentially based on some details of the C++ Function Overload Resolution rules, which can be found, for example, at <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/overload_resolution.\">https:\/\/en.cppreference.com\/w\/cpp\/language\/overload_resolution.<\/a> for example. The first rule used in this is: &#8220;Conversion that converts pointer-to-derived to pointer-to-base is better than the conversion of pointer-to-derived to pointer-to-void,&#8221;<\/p>\n<p>An example of this is Program1.cpp<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ Program1.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Base {};\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Derived <span style=\"color: #555555;\">:<\/span> <span style=\"color: #006699; font-weight: bold;\">public<\/span> Base {};\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> A {};\r\n<span style=\"color: #0099ff; font-style: italic;\">\/\/ Conversion that converts pointer-to-derived to pointer-to-base<\/span>\r\n<span style=\"color: #0099ff; font-style: italic;\">\/\/ is better than the conversion of pointer-to-derived to pointer-to-void,<\/span>\r\n<span style=\"color: #0099ff; font-style: italic;\">\/\/ https:\/\/en.cppreference.com\/w\/cpp\/language\/overload_resolution<\/span>\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">f<\/span>(<span style=\"color: #007788; font-weight: bold;\">void<\/span><span style=\"color: #555555;\">*<\/span>)\r\n{\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"f(void*)\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n}\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">f<\/span>(<span style=\"color: #006699; font-weight: bold;\">const<\/span> Base<span style=\"color: #555555;\">*<\/span>)\r\n{\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"f(Base*)\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n}\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>()\r\n{\r\n    Derived d;\r\n    A a;\r\n    f(<span style=\"color: #555555;\">&amp;<\/span>d);\r\n    f(<span style=\"color: #555555;\">&amp;<\/span>a);\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #ff6600;\">0<\/span>;\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The output is<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\">f(base<span style=\"color: #555555;\">*<\/span>)\r\nf(<span style=\"color: #007788; font-weight: bold;\">void<\/span><span style=\"color: #555555;\">*<\/span>)\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<h3>Program2.cpp<\/h3>\n<p>This rule can distinguish a pointer to a derived class from another pointer. From this, a type trait can be constructed as in Program2.cpp:<\/p>\n<p>&nbsp;<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ Program2.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #006699; font-weight: bold;\">namespace<\/span> details\r\n{\r\n    <span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> B<span style=\"color: #555555;\">&gt;<\/span>\r\n    std<span style=\"color: #555555;\">::<\/span>true_type test_pre_ptr_convertible(<span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #006699; font-weight: bold;\">volatile<\/span> B <span style=\"color: #555555;\">*<\/span>);\r\n    <span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span><span style=\"color: #555555;\">&gt;<\/span>\r\n    std<span style=\"color: #555555;\">::<\/span>false_type test_pre_ptr_convertible(<span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #006699; font-weight: bold;\">volatile<\/span> <span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #555555;\">*<\/span>);\r\n}\r\n<span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> Base, <span style=\"color: #006699; font-weight: bold;\">typename<\/span> Derived<span style=\"color: #555555;\">&gt;<\/span>\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> is_base_of <span style=\"color: #555555;\">:<\/span> std<span style=\"color: #555555;\">::<\/span>integral_constant<span style=\"color: #555555;\">&lt;<\/span>\r\n                        <span style=\"color: #007788; font-weight: bold;\">bool<\/span>,\r\n                        std<span style=\"color: #555555;\">::<\/span>is_class<span style=\"color: #555555;\">&lt;<\/span>Base<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&amp;&amp;<\/span> std<span style=\"color: #555555;\">::<\/span>is_class<span style=\"color: #555555;\">&lt;<\/span>Derived<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&amp;&amp;<\/span>\r\n                             decltype(details<span style=\"color: #555555;\">::<\/span>test_pre_ptr_convertible<span style=\"color: #555555;\">&lt;<\/span>Base<span style=\"color: #555555;\">&gt;<\/span>\r\n                             (<span style=\"color: #006699; font-weight: bold;\">static_cast<\/span><span style=\"color: #555555;\">&lt;<\/span>Derived <span style=\"color: #555555;\">*&gt;<\/span>(nullptr)))<span style=\"color: #555555;\">::<\/span>value\r\n                        <span style=\"color: #555555;\">&gt;<\/span> { };\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Base {};\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Derived <span style=\"color: #555555;\">:<\/span> <span style=\"color: #006699; font-weight: bold;\">public<\/span> Base {};\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> A {};\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>()\r\n{\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>boolalpha;\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"Base is base of Derived: \"<\/span>\r\n              <span style=\"color: #555555;\">&lt;&lt;<\/span> is_base_of<span style=\"color: #555555;\">&lt;<\/span>Base, Derived<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"Derived is base of Base: \"<\/span>\r\n              <span style=\"color: #555555;\">&lt;&lt;<\/span> is_base_of<span style=\"color: #555555;\">&lt;<\/span>Derived, Base<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"Base is base of A: \"<\/span>\r\n              <span style=\"color: #555555;\">&lt;&lt;<\/span> is_base_of<span style=\"color: #555555;\">&lt;<\/span>Base, A<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"Base is base of Base: \"<\/span>\r\n              <span style=\"color: #555555;\">&lt;&lt;<\/span> is_base_of<span style=\"color: #555555;\">&lt;<\/span>Base, Base<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"Base is base of const Derived: \"<\/span>\r\n              <span style=\"color: #555555;\">&lt;&lt;<\/span> is_base_of<span style=\"color: #555555;\">&lt;<\/span>Base, <span style=\"color: #006699; font-weight: bold;\">const<\/span> Derived<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"int is base of int: \"<\/span>\r\n              <span style=\"color: #555555;\">&lt;&lt;<\/span> is_base_of<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span>, <span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"void is base of void: \"<\/span>\r\n              <span style=\"color: #555555;\">&lt;&lt;<\/span> is_base_of<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">void<\/span>, <span style=\"color: #007788; font-weight: bold;\">void<\/span><span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"void is base of Base: \"<\/span> <span style=\"color: #555555;\">&lt;<\/span> <span style=\"color: #555555;\">&lt;<\/span> is_base_of<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">void<\/span>, Base<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #ff6600;\">0<\/span>;\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>t<code>est_pre_ptr_convertible<\/code> are two functions with different argument types and different types of return values. The functions are declared. An implementation of the function body is not necessary since they are never actually called, but only at compile time the type of the return value is queried: <code>test_pre_ptr_convertible&lt;Base&gt;(static_cast&lt;Derived*&gt;(nullptr)<\/code>. If <code>Derived<\/code> is derived from <code>Base<\/code>, the function<code> test_pre_ptr_convertible(const volatile B*)<\/code> with return type <code>std::true_type<\/code> is selected; the return type is determined with <code>decltype<\/code> and the static variable value associated with the type has the value <code>true<\/code>. If <code>Derived<\/code> is not derived from <code>Base<\/code>, the function <code>test_pre_ptr_convertible(const volatile volatile*)<\/code> with return type <code>std::false_type<\/code> is selected, and the corresponding static variable value has the value <code>false<\/code>.<br \/><code><\/code><code>const volatile<\/code> is necessary so that <code>const<\/code> <code>Derived<\/code> or <code>volatile<\/code> <code>Derived<\/code> can be recognized as derived from <code>base<\/code>. In the implementation, a class is also considered as a base of its itself, so i<code>s_base_of&lt;base,base&gt;<\/code> returns <code>true<\/code>.<br \/>Since derivation only makes sense for classes, the following is used <code>std::is_class&lt;Base&gt;::value &amp;&amp; std::is_class&lt;Derived&gt;::value<\/code> so that e.g. <code>is_base_of&lt;int,int&gt;::value<\/code> returns <code>false<\/code>.<\/p>\n<h3>Program3.cpp<\/h3>\n<p>At first glance, it looks like Program2.cpp already does what it should. However, C++ supports multiple inheritances. Therefore a base class may occur multiple times in the derivation hierarchy. This can be tested with Program3.cpp:<\/p>\n<p>&nbsp;<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ Program3.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #006699; font-weight: bold;\">namespace<\/span> details\r\n{\r\n    <span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> B<span style=\"color: #555555;\">&gt;<\/span>\r\n    std<span style=\"color: #555555;\">::<\/span>true_type test_pre_ptr_convertible(<span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #006699; font-weight: bold;\">volatile<\/span> B <span style=\"color: #555555;\">*<\/span>);\r\n    <span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span><span style=\"color: #555555;\">&gt;<\/span>\r\n    std<span style=\"color: #555555;\">::<\/span>false_type test_pre_ptr_convertible(<span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #006699; font-weight: bold;\">volatile<\/span> <span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #555555;\">*<\/span>);\r\n}\r\n<span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> Base, <span style=\"color: #006699; font-weight: bold;\">typename<\/span> Derived<span style=\"color: #555555;\">&gt;<\/span>\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> is_base_of <span style=\"color: #555555;\">:<\/span> std<span style=\"color: #555555;\">::<\/span>integral_constant<span style=\"color: #555555;\">&lt;<\/span>\r\n                        <span style=\"color: #007788; font-weight: bold;\">bool<\/span>,\r\n                        std<span style=\"color: #555555;\">::<\/span>is_class<span style=\"color: #555555;\">&lt;<\/span>Base<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&amp;&amp;<\/span>\r\n                            std<span style=\"color: #555555;\">::<\/span>is_class<span style=\"color: #555555;\">&lt;<\/span>Derived<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&amp;&amp;<br \/>                            <\/span>decltype(details<span style=\"color: #555555;\">::<\/span>test_pre_ptr_convertible<span style=\"color: #555555;\">&lt;<\/span>Base<span style=\"color: #555555;\">&gt;<br \/>                            <\/span>(<span style=\"color: #006699; font-weight: bold;\">static_cast<\/span><span style=\"color: #555555;\">&lt;<\/span>Derived <span style=\"color: #555555;\">*&gt;<\/span>(nullptr)))<span style=\"color: #555555;\">::<\/span>value<br \/>                        <span style=\"color: #555555;\">&gt;<\/span>{ };\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Base {};\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Derived1 <span style=\"color: #555555;\">:<\/span> <span style=\"color: #006699; font-weight: bold;\">public<\/span> Base {};\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Derived2 <span style=\"color: #555555;\">:<\/span> <span style=\"color: #006699; font-weight: bold;\">public<\/span> Base { };\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Multi <span style=\"color: #555555;\">:<\/span> <span style=\"color: #006699; font-weight: bold;\">public<\/span> Derived1, <span style=\"color: #006699; font-weight: bold;\">public<\/span> Derived2\r\n{\r\n};\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>()\r\n{\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>boolalpha;\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ error: \u2018Base\u2019 is an ambiguous base of \u2018Multi\u2019<\/span>\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"Base is base of Multi: \"<\/span>\r\n              <span style=\"color: #555555;\">&lt;&lt;<\/span> is_base_of<span style=\"color: #555555;\">&lt;<\/span>Base, Multi<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #ff6600;\">0<\/span>;\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The compiler now returns the error message<br \/><code>error: 'Base' is an ambiguous base of 'Multi'<\/code><\/p>\n<h3>Program4.cpp<\/h3>\n<p>To get unambiguousness again, SFINAE and an extra level of indirection (in the form of the function <code>test_pre_is_base_of<\/code>) are useful:<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ Program4.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #006699; font-weight: bold;\">namespace<\/span> details\r\n{\r\n    <span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> B<span style=\"color: #555555;\">&gt;<\/span>\r\n    std<span style=\"color: #555555;\">::<\/span>true_type test_pre_ptr_convertible(<span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #006699; font-weight: bold;\">volatile<\/span> B <span style=\"color: #555555;\">*<\/span>);\r\n    <span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span><span style=\"color: #555555;\">&gt;<\/span>\r\n    std<span style=\"color: #555555;\">::<\/span>false_type test_pre_ptr_convertible(<span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #006699; font-weight: bold;\">volatile<\/span> <span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #555555;\">*<\/span>);\r\n    <span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span>, <span style=\"color: #006699; font-weight: bold;\">typename<\/span><span style=\"color: #555555;\">&gt;<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">auto<\/span> test_pre_is_base_of() <span style=\"color: #555555;\">-&gt;<\/span> std<span style=\"color: #555555;\">::<\/span>true_type;\r\n    <span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> B, <span style=\"color: #006699; font-weight: bold;\">typename<\/span> D<span style=\"color: #555555;\">&gt;<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">auto<\/span> test_pre_is_base_of() <span style=\"color: #555555;\">-&gt;<\/span> decltype(test_pre_ptr_convertible<span style=\"color: #555555;\">&lt;<\/span>B<span style=\"color: #555555;\">&gt;<\/span>(<span style=\"color: #006699; font-weight: bold;\">static_cast<\/span><span style=\"color: #555555;\">&lt;<\/span>D <span style=\"color: #555555;\">*&gt;<\/span>(nullptr)));\r\n}\r\n<span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> Base, <span style=\"color: #006699; font-weight: bold;\">typename<\/span> Derived<span style=\"color: #555555;\">&gt;<\/span>\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> is_base_of <span style=\"color: #555555;\">:<\/span> std<span style=\"color: #555555;\">::<\/span>integral_constant<span style=\"color: #555555;\">&lt;<\/span>\r\n                        <span style=\"color: #007788; font-weight: bold;\">bool<\/span>,\r\n                        std<span style=\"color: #555555;\">::<\/span>is_class<span style=\"color: #555555;\">&lt;<\/span>Base<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&amp;&amp;<\/span> \r\n                        std<span style=\"color: #555555;\">::<\/span>is_class<span style=\"color: #555555;\">&lt;<\/span>Derived<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&amp;&amp;<\/span> \r\n                        decltype(details<span style=\"color: #555555;\">::<\/span>test_pre_is_base_of<span style=\"color: #555555;\">&lt;<\/span>Base, Derived<span style=\"color: #555555;\">&gt;<\/span>())<span style=\"color: #555555;\">::<\/span>value<br \/>                    <span style=\"color: #555555;\">&gt; <\/span>{};\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Base {};\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Derived1 <span style=\"color: #555555;\">:<\/span> <span style=\"color: #006699; font-weight: bold;\">public<\/span> Base {};\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Derived2 <span style=\"color: #555555;\">:<\/span> <span style=\"color: #006699; font-weight: bold;\">public<\/span> Base {};\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Multi <span style=\"color: #555555;\">:<\/span> <span style=\"color: #006699; font-weight: bold;\">public<\/span> Derived1, <span style=\"color: #006699; font-weight: bold;\">public<\/span> Derived2 {};\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>()\r\n{\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>boolalpha;\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"Base is base of Multi: \"<\/span>\r\n              <span style=\"color: #555555;\">&lt;&lt;<\/span> is_base_of<span style=\"color: #555555;\">&lt;<\/span>Base, Multi<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ error: call of overloaded \u2018test_pre_is_base_of&lt;Derived2, Multi&gt;()\u2019<\/span>\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ is ambiguous<\/span>\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ std::cout &lt;&lt; \"Base is base of Derived1: \"<\/span>\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/&lt;&lt; is_base_of&lt;Base, Derived1&gt;::value &lt;&lt; \"\\n\";<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #ff6600;\">0<\/span>;\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>For the function call<br \/><code>test_pre_is_base_of&lt;base,multi&gt;()<\/code><br \/>the two functions<br \/><code>template &lt;typename B, typename D&gt;<br \/>&nbsp;&nbsp;&nbsp; auto test_pre_is_base_of() -&gt;<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; decltype(test_pre_ptr_convertible&lt;B&gt;(static_cast&lt;D*&gt;(nullptr)));<\/code><br \/>and<br \/> <code>template&lt;typename, typename&gt;.<br \/> auto test_pre_is_base_of() -&gt; std::true_type;<\/code><br \/>can be choosen. The function call<br \/><code>test_pre_ptr_convertible&lt;base&gt;(static_cast&lt;multi*&gt;(nullptr))<\/code><br \/>calls<br \/>t<code>est_pre_ptr_convertible(const volatile Base*);<\/code><br \/>. But this is ambiguous since it is not clear to which of the two bases of <code>Multi<\/code> the pointer <code>Base<\/code>* should point. So this gives a &#8220;substitution failure&#8221;. But since a &#8220;substitution failure&#8221; is not an &#8220;error&#8221;, the other function<br \/>te<code>mplate &lt;typename, typename&gt;<br \/>&nbsp;&nbsp;&nbsp;&nbsp; auto test_pre_is_base_of() -&gt; std::true_type;<\/code><br \/>is checked. This is valid, so it returns<br \/><code>decltype(details::test_pre_is_base_of&lt;base,multi&gt;())::value<\/code><br \/>returns the value true via this path.<br \/>Unfortunately, however, this type trait no longer works for simple base classes<br \/><code>is_base_of&lt;base,derived1&gt;::value<\/code><br \/>because in this case both functions<br \/><code>template &lt;typename B, typename D&gt;<br \/>&nbsp;&nbsp;&nbsp; auto test_pre_is_base_of() -&gt;<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; decltype(test_pre_ptr_convertible&lt;B&gt;(static_cast&lt;D*&gt;(nullptr)));<\/code><br \/>and<br \/>&nbsp;&nbsp;&nbsp; <code>template&lt;typename, typename&gt;<br \/>&nbsp; auto test_pre_is_base_of() -&gt; std::true_type;<\/code><br \/>are valid and equivalent according to the Function Overload Resolution rules. Therefore, to solve this problem, it is necessary to somehow enforce that first<br \/><code>template &lt;typename B, typename D&gt;<br \/>&nbsp;&nbsp;&nbsp; auto test_pre_is_base_of() -&gt;<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; decltype(test_pre_ptr_convertible&lt;B&gt;(static_cast&lt;D*&gt;(nullptr)));<\/code><br \/>is selected, and<br \/><code>template &lt;typename, typename&gt;<br \/>&nbsp;&nbsp;&nbsp; auto test_pre_is_base_of() -&gt; std::true_type;<\/code><br \/>is chosen only if the first function returns a substitution failure.<\/p>\n<h3>Program5.cpp<\/h3>\n<p>A solution for this also exists: &#8220;A standard conversion sequence is always better than a user-defined conversion sequence or an ellipsis conversion sequence.&#8221;<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ Program5.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #006699; font-weight: bold;\">namespace<\/span> details\r\n{\r\n    <span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> B<span style=\"color: #555555;\">&gt;<\/span>\r\n    std<span style=\"color: #555555;\">::<\/span>true_type test_pre_ptr_convertible(<span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #006699; font-weight: bold;\">volatile<\/span> B <span style=\"color: #555555;\">*<\/span>);\r\n    <span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span><span style=\"color: #555555;\">&gt;<\/span>\r\n    std<span style=\"color: #555555;\">::<\/span>false_type test_pre_ptr_convertible(<span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #006699; font-weight: bold;\">volatile<\/span> <span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #555555;\">*<\/span>);\r\n    <span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span>, <span style=\"color: #006699; font-weight: bold;\">typename<\/span><span style=\"color: #555555;\">&gt;<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">auto<\/span> test_pre_is_base_of(...) <span style=\"color: #555555;\">-&gt;<\/span> std<span style=\"color: #555555;\">::<\/span>true_type;\r\n    <span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> B, <span style=\"color: #006699; font-weight: bold;\">typename<\/span> D<span style=\"color: #555555;\">&gt;<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">auto<\/span> test_pre_is_base_of(<span style=\"color: #007788; font-weight: bold;\">int<\/span>) <span style=\"color: #555555;\">-&gt;<\/span> decltype(test_pre_ptr_convertible<span style=\"color: #555555;\">&lt;<\/span>B<span style=\"color: #555555;\">&gt;<\/span>(<span style=\"color: #006699; font-weight: bold;\">static_cast<\/span><span style=\"color: #555555;\">&lt;<\/span>D <span style=\"color: #555555;\">*&gt;<\/span>(nullptr)));\r\n}\r\n<span style=\"color: #0099ff; font-style: italic;\">\/\/ A standard conversion sequence is always better<\/span>\r\n<span style=\"color: #0099ff; font-style: italic;\">\/\/ than a user-defined conversion sequence<\/span>\r\n<span style=\"color: #0099ff; font-style: italic;\">\/\/ or an ellipsis conversion sequence.<\/span>\r\n<span style=\"color: #0099ff; font-style: italic;\">\/\/ https:\/\/en.cppreference.com\/w\/cpp\/language\/overload_resolution<\/span>\r\n<span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> Base, <span style=\"color: #006699; font-weight: bold;\">typename<\/span> Derived<span style=\"color: #555555;\">&gt;<\/span>\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> is_base_of <span style=\"color: #555555;\">:<\/span> std<span style=\"color: #555555;\">::<\/span>integral_constant<span style=\"color: #555555;\">&lt;<\/span>\r\n                        <span style=\"color: #007788; font-weight: bold;\">bool<\/span>,\r\n                        std<span style=\"color: #555555;\">::<\/span>is_class<span style=\"color: #555555;\">&lt;<\/span>Base<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&amp;&amp;<\/span> std<span style=\"color: #555555;\">::<\/span>is_class<span style=\"color: #555555;\">&lt;<\/span>Derived<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&amp;&amp;<br \/>                        <\/span>decltype(details<span style=\"color: #555555;\">::<\/span>test_pre_is_base_of<span style=\"color: #555555;\">&lt;<\/span>Base, Derived<span style=\"color: #555555;\">&gt;<\/span>(<span style=\"color: #ff6600;\">0<\/span>))<span style=\"color: #555555;\">::<\/span>value<br \/>                   <span style=\"color: #555555;\">&gt; <\/span>{};\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Base {};\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Derived1 <span style=\"color: #555555;\">:<\/span> <span style=\"color: #006699; font-weight: bold;\">public<\/span> Base {};\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Derived2 <span style=\"color: #555555;\">:<\/span> <span style=\"color: #006699; font-weight: bold;\">public<\/span> Base {};\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Multi <span style=\"color: #555555;\">:<\/span> <span style=\"color: #006699; font-weight: bold;\">public<\/span> Derived1, <span style=\"color: #006699; font-weight: bold;\">public<\/span> Derived2{};\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>()\r\n{\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>boolalpha;\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"Base is base of Derived1: \"<\/span>\r\n              <span style=\"color: #555555;\">&lt;&lt;<\/span> is_base_of<span style=\"color: #555555;\">&lt;<\/span>Base, Derived1<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"Derived1 is base of Base: \"<\/span>\r\n              <span style=\"color: #555555;\">&lt;&lt;<\/span> is_base_of<span style=\"color: #555555;\">&lt;<\/span>Derived1, Base<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"Base is base of Derived2: \"<\/span>\r\n              <span style=\"color: #555555;\">&lt;&lt;<\/span> is_base_of<span style=\"color: #555555;\">&lt;<\/span>Base, Derived2<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"Derived2 is base of Base: \"<\/span>\r\n              <span style=\"color: #555555;\">&lt;&lt;<\/span> is_base_of<span style=\"color: #555555;\">&lt;<\/span>Derived2, Base<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"Derived1 is base of Multi: \"<\/span>\r\n              <span style=\"color: #555555;\">&lt;&lt;<\/span> is_base_of<span style=\"color: #555555;\">&lt;<\/span>Derived1, Multi<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"Derived2 is base of Multi: \"<\/span>\r\n              <span style=\"color: #555555;\">&lt;&lt;<\/span> is_base_of<span style=\"color: #555555;\">&lt;<\/span>Derived2, Multi<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"Base is base of Multi: \"<\/span>\r\n              <span style=\"color: #555555;\">&lt;&lt;<\/span> is_base_of<span style=\"color: #555555;\">&lt;<\/span>Base, Multi<span style=\"color: #555555;\">&gt;::<\/span>value <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #ff6600;\">0<\/span>;\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>If one uses<br \/>t<code>emplate &lt;typename B, typename D&gt;<br \/>&nbsp;&nbsp;&nbsp; auto test_pre_is_base_of(int) -&gt;<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; decltype(test_pre_ptr_convertible&lt;B&gt;(static_cast&lt;D*&gt;(nullptr)));<\/code><br \/>(i.e. a &#8220;standard conversion&#8221; to <code>int<\/code>), and<br \/><code>template &lt;typename, typename&gt;<br \/>&nbsp;&nbsp;&nbsp; auto test_pre_is_base_of(...) -&gt; std::true_type;<\/code><br \/>(i.e. an &#8220;ellipsis&#8221;), then the first function (standard conversion) is selected preferentially and the second (ellipsis) actually only in the SFINAE case. So the type trait works both for multiple as well as for simple base classes.<\/p>\n<h2>What&#8217;s next?<\/h2>\n<p>With the type traits library, you can check or compare types and modify them. This is exactly what my next article will deal with.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I finished the last article on the Type-Traits library with the challenge of explaining the std::is_base_of and std::is_convertible functions. Today I&#8217;m excited to present the answer from Mr. Helmut Zeisel.<\/p>\n","protected":false},"author":21,"featured_media":6251,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[376],"tags":[419],"class_list":["post-6257","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-templates","tag-type-traits"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6257","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/users\/21"}],"replies":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/comments?post=6257"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6257\/revisions"}],"predecessor-version":[{"id":6689,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6257\/revisions\/6689"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/6251"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=6257"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=6257"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=6257"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}