{"id":1592,"date":"2024-02-20T08:43:23","date_gmt":"2024-02-20T08:43:23","guid":{"rendered":"https:\/\/cppdepend.com\/blog\/?p=1592"},"modified":"2024-05-22T11:00:34","modified_gmt":"2024-05-22T11:00:34","slug":"c-is-now-a-feature-rich-language-be-aware-of-overengeniering","status":"publish","type":"post","link":"https:\/\/cppdepend.com\/blog\/c-is-now-a-feature-rich-language-be-aware-of-overengeniering\/","title":{"rendered":"C++ is now a feature-rich language, Be aware of OverEngineering"},"content":{"rendered":"\n<p>Being aware of overengineering is crucial when working with a feature-rich language like C++. Overengineering occurs when developers introduce overly complex or unnecessary solutions to a problem.<\/p>\n\n\n\n<p>C++ developers could be attempted to use as possible the new features introduced by the new standards. which makes the code finally more complicated than it must be.<\/p><p>Here&#8217;s an example to show  how C++ metaprogramming can be used to create a type-erased container with arithmetic operations that are evaluated at compile time. While this example show the power and flexibility of C++ metaprogramming techniques. it might seem complicated due to the use of templates, concepts and constexpr functions:<\/p>\n\n\n\n<!--more-->\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:false,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;htmlmixed&quot;,&quot;mime&quot;:&quot;text\/html&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;HTML&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;html&quot;}\">#include &lt;iostream&gt;\n#include &lt;type_traits&gt;\n\ntemplate&lt;typename T&gt;\nconcept Arithmetic = std::is_arithmetic_v&lt;T&gt;;\n\ntemplate&lt;Arithmetic T&gt;\nstruct AnyType {\n    constexpr AnyType(const T&amp; value) : value_(value) {}\n\n    template&lt;Arithmetic U&gt;\n    constexpr auto add(const AnyType&lt;U&gt;&amp; other) const {\n        return AnyType{ value_ + other.value_ };\n    }\n\n    template&lt;Arithmetic U&gt;\n    constexpr auto subtract(const AnyType&lt;U&gt;&amp; other) const {\n        return AnyType{ value_ - other.value_ };\n    }\n\n    template&lt;Arithmetic U&gt;\n    constexpr auto multiply(const AnyType&lt;U&gt;&amp; other) const {\n        return AnyType{ value_ * other.value_ };\n    }\n\n    template&lt;Arithmetic U&gt;\n    constexpr auto divide(const AnyType&lt;U&gt;&amp; other) const {\n        static_assert(other.value_ != 0, &quot;Division by zero&quot;);\n        return AnyType{ value_ \/ other.value_ };\n    }\n\n    template&lt;Arithmetic U&gt;\n    friend std::ostream&amp; operator&lt;&lt;(std::ostream&amp; os, const AnyType&lt;U&gt;&amp; any) {\n        return os &lt;&lt; any.value_;\n    }\n\nprivate:\n    T value_;\n};\n\nint main() {\n    constexpr AnyType&lt;int&gt; x{ 5 };\n    constexpr AnyType&lt;float&gt; y{ 2.5f };\n\n    constexpr auto addition = x.add(y);\n    constexpr auto subtraction = x.subtract(y);\n    constexpr auto multiplication = x.multiply(y);\n    constexpr auto division = x.divide(y);\n\n    std::cout &lt;&lt; &quot;Addition: &quot; &lt;&lt; addition &lt;&lt; std::endl;\n    std::cout &lt;&lt; &quot;Subtraction: &quot; &lt;&lt; subtraction &lt;&lt; std::endl;\n    std::cout &lt;&lt; &quot;Multiplication: &quot; &lt;&lt; multiplication &lt;&lt; std::endl;\n    std::cout &lt;&lt; &quot;Division: &quot; &lt;&lt; division &lt;&lt; std::endl;\n\n    return 0;\n}\n<\/pre><\/div>\n\n\n\n<p>In this example:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>We define a concept <code>Arithmetic<\/code> to constrain the template parameters to arithmetic types.<\/li>\n\n\n\n<li>The <code>AnyType<\/code> class template is defined to hold any arithmetic type.<\/li>\n\n\n\n<li>We provide member functions (<code>add<\/code>, <code>subtract<\/code>, <code>multiply<\/code>, <code>divide<\/code>) that perform arithmetic operations between <code>AnyType<\/code> objects of potentially different types.<\/li>\n\n\n\n<li>We use <code>constexpr<\/code> to ensure that these operations are evaluated at compile time.<\/li>\n\n\n\n<li>We overload the <code>operator&lt;&lt;<\/code> to allow streaming <code>AnyType<\/code> objects to <code>std::ostream<\/code>.<\/li>\n<\/ul>\n\n\n\n<p>Yes sometimes for specific needs we can develop a code like that, But in general do we need this sophisticated class to do basic arithmetic operations, it&#8217;s like construct a tank to kill a fly \ud83d\ude42<\/p>\n\n\n\n<p>To resume try to not be tempted by the sophiscated new features and try to use them only if you need to. And always try to <strong>Follow KISS and YAGNI Principles<\/strong>:<\/p>\n\n\n\n<p>Keep It Simple, Stupid (KISS) and You Ain&#8217;t Gonna Need It (YAGNI) are principles that advocate for simplicity and avoiding unnecessary features until they are needed.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Being aware of overengineering is crucial when working with a feature-rich language like C++. Overengineering occurs when developers introduce overly complex or unnecessary solutions to a problem. C++ developers could be attempted to use as possible the new features introduced by the new standards. which makes the code finally more complicated than it must be. &hellip; <a href=\"https:\/\/cppdepend.com\/blog\/c-is-now-a-feature-rich-language-be-aware-of-overengeniering\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;C++ is now a feature-rich language, Be aware of OverEngineering&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[67,137],"class_list":["post-1592","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-c-2","tag-programming"],"_links":{"self":[{"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/posts\/1592","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/comments?post=1592"}],"version-history":[{"count":6,"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/posts\/1592\/revisions"}],"predecessor-version":[{"id":1776,"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/posts\/1592\/revisions\/1776"}],"wp:attachment":[{"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/media?parent=1592"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/categories?post=1592"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/tags?post=1592"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}