<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Helio Nunes Santos</title>
    <description>The latest articles on DEV Community by Helio Nunes Santos (@heliobatimarqui).</description>
    <link>https://dev.to/heliobatimarqui</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F447736%2F65124ea0-78ef-4d5f-ac17-640fb6049cd8.jpeg</url>
      <title>DEV Community: Helio Nunes Santos</title>
      <link>https://dev.to/heliobatimarqui</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/heliobatimarqui"/>
    <language>en</language>
    <item>
      <title>How I am handling errors in a freestanding environment</title>
      <dc:creator>Helio Nunes Santos</dc:creator>
      <pubDate>Thu, 05 May 2022 23:22:03 +0000</pubDate>
      <link>https://dev.to/heliobatimarqui/how-i-am-handling-errors-in-a-freestanding-environment-3gda</link>
      <guid>https://dev.to/heliobatimarqui/how-i-am-handling-errors-in-a-freestanding-environment-3gda</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Hi guys!&lt;/p&gt;

&lt;p&gt;It has been a good while since I have written anything (well, I actually have written an article just once), but as I have gotten inspiration from a myriad of things recently, I have decided to start writing more, to showcase what I am working on and receive feedback on my code.&lt;/p&gt;

&lt;p&gt;I will tell you guys a small story and then we can proceed to the meat. If you want, you can skip the next part.&lt;/p&gt;

&lt;h2&gt;
  
  
  The story behind it
&lt;/h2&gt;

&lt;p&gt;I have recently discovered the RISC-V ISA, which is an open instruction set architecture. With the RISC-V ISA if you want to develop a new CPU that supports the architecture. you don't have to pay royalties to anyone and, for me at least, it sounds amazing! It can also open doors to endless possibilities if the architecture succeeds and is widely adopted and produced, given that not paying royalties could be another factor in decreasing the cost of CPUs, which in turn can encourage more innovation (not that we are not facing any currently).&lt;/p&gt;

&lt;p&gt;Given my interest in the architecture and its proposed benefits, I have decided to take my time to develop a small kernel for it. I am not being the first one to do so, but I have decided to do this as a challenge to myself, given that developing a kernel is not an easy task and it is going to make me get a good grasp of a lot of Computer Science concepts. As the architecture doesn't have to be compatible with anything developed more than 40 years ago (cough cough x86), it is easier to have it as a target for a brand new kernel.&lt;/p&gt;

&lt;p&gt;Right at the beginning of developing the kernel, I had to figure out a way of dealing with errors. Given that my kernel gets the address of the Device Tree (a structure used to describe the system's physical hardware) from the arguments that are passed to its start function, I have to read the arguments and parse the value which contains the address in hexadecimal for the Flattened Device Tree.&lt;/p&gt;

&lt;p&gt;Given that I am in a freestanding environment, I have to implement from scratch almost everything, which includes a routine to parse a string that contains (or not) a value in hexadecimal.&lt;/p&gt;

&lt;p&gt;Now, how can I handle errors? An example would be when the user supplies garbage instead of an hexadecimal value.&lt;/p&gt;

&lt;p&gt;In a freestanding environment, there are no exceptions, so using them is ruled out. &lt;/p&gt;

&lt;p&gt;One idea would be to determine certain values as errors, which is how a lot of softwares developed in C do. But I would have to say that it is not the ideal solution, given that, for example, if I get 0 as the value to indicate an error, how can I be sure that the user really didn't give 0 as an argument? Surely, for the address of the Device Tree, 0 wouldn't be a valid value, but I will be reusing the routine to parse hexadecimals in other cases as well, and 0 might be a valid value. Of course, when applicable, I could simply check if it is a value that represent an error, but this would demand developing a different logic for errors each time, which can be tiresome and bug prone.&lt;/p&gt;

&lt;p&gt;I could also use retrieve errors from global variables, but I am planning to support multi-threading in the future, so this option would add unnecessary complexity to my code.&lt;/p&gt;

&lt;p&gt;As this small case has given me food for thought, I remembered of a talk I have seen a while ago and decided to go with the idea presented. We are using a multi-paradigm programming language, so why not take advantage of this?&lt;br&gt;
We can simply have a safe union that indicates whether we have a value or an error and contains either of both. Doing like this, we don't have to reserve a value to indicate an error, and it helps us to handle the error logic separately, given that we have a whole range of values to use as error values!&lt;/p&gt;
&lt;h2&gt;
  
  
  How I am doing it
&lt;/h2&gt;

&lt;p&gt;So, for handling errors, I am using a small class that I called ValueOrError. It has a simple interface which allows the user to know if what it holds is either a value or an error value and get what it holds accordingly.&lt;/p&gt;

&lt;p&gt;To make it more expressive and easier for the user, I had to define a class called GenericWrapper, which is a wrapper over a value. &lt;/p&gt;

&lt;p&gt;Here is the preamble of the header file which contains the class ValueOrError. This preamble contains a few declarations (that will be explained later) and the definition of the class GenericWrapper.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include &amp;lt;utility&amp;gt;
#include &amp;lt;type_traits&amp;gt;

namespace hls {

    template&amp;lt;typename, typename&amp;gt;
    class ValueOrError;

    template&amp;lt;typename T, int x&amp;gt;
    class GenericWrapper;

    template&amp;lt;typename T&amp;gt;
    using ErrorType = GenericWrapper&amp;lt;T, 0&amp;gt;;

    template&amp;lt;typename T&amp;gt;
    using ValueType = GenericWrapper&amp;lt;T, 1&amp;gt;;

    template&amp;lt;typename T, int x&amp;gt;
    class GenericWrapper {
        T v;
        GenericWrapper(T&amp;amp;&amp;amp; a) : v(std::forward&amp;lt;T&amp;gt;(a)) {};
        GenericWrapper(const T&amp;amp; a) : v(a) {};
        GenericWrapper(const GenericWrapper&amp;amp;) = default;
        GenericWrapper(GenericWrapper&amp;amp;&amp;amp;) = default;
    public:
        ~GenericWrapper() = default;

        template&amp;lt;typename, typename&amp;gt;
        friend class ValueOrError;

        template&amp;lt;typename U&amp;gt;
        friend auto error(U&amp;amp;&amp;amp; error) -&amp;gt; ErrorType&amp;lt;std::remove_cvref_t&amp;lt;U&amp;gt;&amp;gt;;

        template&amp;lt;typename U&amp;gt;
        friend auto value(U&amp;amp;&amp;amp; value) -&amp;gt; GenericWrapper&amp;lt;std::remove_cvref_t&amp;lt;U&amp;gt;, 1&amp;gt;;

    };

    // Remaining of the file...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Have you seen the declaration of those two friend functions at the bottom? These two are the ones that will help giving more expressiveness to the code! Have you also seen the using declarations for ErrorType and ValueType? I will be taking advantage of the C++ type system to conform with DRY (Don't repeat yourself).&lt;/p&gt;

&lt;p&gt;Whenever a user wants to return a value or an error, they can simply do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#define ERROR_FOR_REASON_X 10
ValueOrError&amp;lt;int, int&amp;gt; my_function(int input_value) {
    // Do stuff based on input_value
    // Nice, we didn't get an error
    if(all_good)
        return hls::value(10);
    // Oh no, we got an error
    else 
        return hls::error(ERROR_FOR_REASON_X);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Have you seen that we used the same value for the return value and for the reason of the error? That is where our class ValueOrError comes. Here is the remaining of the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    template&amp;lt;typename T&amp;gt;
    auto error(T&amp;amp;&amp;amp; error) -&amp;gt; ErrorType&amp;lt;std::remove_cvref_t&amp;lt;T&amp;gt;&amp;gt; {
        return {std::forward&amp;lt;T&amp;gt;(error)};
    }

    template&amp;lt;typename T&amp;gt;
    auto value(T&amp;amp;&amp;amp; value) -&amp;gt; ValueType&amp;lt;std::remove_cvref_t&amp;lt;T&amp;gt;&amp;gt; {
        return {std::forward&amp;lt;T&amp;gt;(value)};
    }

        template&amp;lt;typename T, typename ErrorT = int&amp;gt;
    class ValueOrError {
        using Type = std::remove_cvref_t&amp;lt;T&amp;gt;;
        using Error = std::remove_cvref_t&amp;lt;ErrorT&amp;gt;;

        union {
            Type value;
            Error error;
        } m_stored;
        bool m_is_error = false;
    public:

        template&amp;lt;typename U&amp;gt;
        requires (std::is_same_v&amp;lt;std::remove_cvref_t&amp;lt;std::remove_pointer_t&amp;lt;U&amp;gt;&amp;gt;, std::remove_cvref_t&amp;lt;std::remove_pointer_t&amp;lt;T&amp;gt;&amp;gt;&amp;gt;)
        ValueOrError(ValueType&amp;lt;U&amp;gt;&amp;amp;&amp;amp; value) {
            new(&amp;amp;m_stored.value)T(std::move(value.v));
        }

        template&amp;lt;typename U&amp;gt;
        requires (std::is_same_v&amp;lt;std::remove_cvref_t&amp;lt;std::remove_pointer_t&amp;lt;U&amp;gt;&amp;gt;, std::remove_cvref_t&amp;lt;std::remove_pointer_t&amp;lt;ErrorT&amp;gt;&amp;gt;&amp;gt;)
        ValueOrError(ErrorType&amp;lt;U&amp;gt;&amp;amp;&amp;amp; error) {
            m_is_error = true;
            new(&amp;amp;m_stored.error)ErrorT(std::move(error.v));
        }

        ~ValueOrError() {
            if(is_error())
                m_stored.error.~ErrorT();
            else
                m_stored.value.~T();
        }

        ValueOrError(const ValueOrError&amp;amp; other) {
            if(other.is_error()) {
                m_is_error = true;
                m_stored.error = other.get_error();
            }
            else {
                m_stored.value = other.get_value();
            } 
        }

        ValueOrError(ValueOrError&amp;amp;&amp;amp; other) {
            if(other.is_error()) {
                m_is_error = true;
                m_stored.error = std::move(other.get_error());
            }
            else {
                m_stored.value = std::move(other.get_value());
            }
        }

        bool is_error() const {
            return m_is_error;
        }

        bool is_value() const {
            return !is_error();
        }

        T&amp;amp; get_value() {
            const auto&amp;amp; as_const = *this;
            return const_cast&amp;lt;T&amp;amp;&amp;gt;(as_const.get_value());
        }

        const T&amp;amp; get_value() const {
            return m_stored.value;
        }

        ErrorT&amp;amp; get_error() {
            const auto&amp;amp; as_const = *this;
            return const_cast&amp;lt;ErrorT&amp;amp;&amp;gt;(as_const.get_error());
        }

        const ErrorT&amp;amp; get_error() const {
            return m_stored.error;
        }
    };

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, the class ValueOrError takes advantage of the fact that using a different value for the template argument creates a different type, which causes the compiler to call the proper constructor. Note also that we have the requires clause as to disallow unintentional type conversion. Without it, you could say &lt;code&gt;hls::value(10.0f)&lt;/code&gt; instead of &lt;code&gt;hls::value(10)&lt;/code&gt; and it would work. If this is desired, a cast then should be used.&lt;/p&gt;

&lt;p&gt;Note that the classes take advantage of move semantics, so the compiler should be able to optimize all of it. &lt;/p&gt;

&lt;p&gt;Last but not least, I will be producing a small example with the usage of it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;
#include &amp;lt;iomanip&amp;gt;
#include "valerror.hpp"

// When not specified, a enum defaults to an int
enum ERROR_CODE {
    INVALID_STRING,
    NOT_AN_HEX_VALUE,
    VALUE_TOO_LARGE
};

hls::ValueOrError&amp;lt;int, ERROR_CODE&amp;gt; hex_to_int(const char* hex_string) {
    if(hex_string == nullptr)
        return hls::error(INVALID_STRING);

    bool is_hex_value;
    // Code that checks if is an hex value
    // ...
    if(!is_hex_value)  
        return hls::error(NOT_AN_HEX_VALUE);

    int required_bit_size;
    // Code that checks if the hex value fits in an int
    // ...
    if(required_bit_size &amp;gt; 32) 
        return hls::error(VALUE_TOO_LARGE);

    int result;
    // Code that converts it to an int
    return hls::value(result); 
};


int main() {

    while(true) {
        std::cout &amp;lt;&amp;lt; "Please, provide an hex value that fits in a 32 bits integer: \n";
        std::string user_input;

        std::cin &amp;gt;&amp;gt; user_input;

        auto result = hex_to_int(user_input.c_str());

        if(result.is_error()) {
            switch(result.get_error()) {
                case INVALID_STRING:
                    std::cout &amp;lt;&amp;lt; "The pointer to the string was nullptr\n";
                    break;
                case NOT_AN_HEX_VALUE:
                    std::cout &amp;lt;&amp;lt; "The user input was not an hex value\n";
                    break;
                case VALUE_TOO_LARGE:
                    std::cout &amp;lt;&amp;lt; "The value the user has given doesn't fit in a 32 bit integer.\n";
                    break;
            }
        }
        else {
            std::cout &amp;lt;&amp;lt; "The user input was: " &amp;lt;&amp;lt; std::setbase(16) &amp;lt;&amp;lt; result.get_value() &amp;lt;&amp;lt; "\n";
            break;
        }    

    }   
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that is it guys. I hope everything was clear. I would also like to have your feedback on improvement and suggestions, be it on my code or my writing. Thank you and see you soon!&lt;/p&gt;

&lt;p&gt;If you want to get in touch with me, add me on LinkedIn:&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/heliobatimarqui/"&gt;https://www.linkedin.com/in/heliobatimarqui/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cpp</category>
      <category>errors</category>
      <category>programming</category>
      <category>kernel</category>
    </item>
    <item>
      <title>Compile time type id with templates (C++)</title>
      <dc:creator>Helio Nunes Santos</dc:creator>
      <pubDate>Mon, 28 Dec 2020 02:17:38 +0000</pubDate>
      <link>https://dev.to/heliobatimarqui/compile-time-type-id-with-templates-c-55c4</link>
      <guid>https://dev.to/heliobatimarqui/compile-time-type-id-with-templates-c-55c4</guid>
      <description>&lt;h2&gt;
  
  
  The issue:
&lt;/h2&gt;

&lt;p&gt;Another day while developing my game engine I had to handle events (which inherited from a common interface). The problem was that handling different event types with RTTI is not good in this case, as it is expensive. If-else statements were quite convoluted, so switch statement to the rescue.&lt;/p&gt;

&lt;p&gt;The problem is that a switch statement requires all values to be known at compile time. Enums could be a solution, but IMO they are messy and have a wide margin for errors.&lt;/p&gt;

&lt;p&gt;I ended up with a solution that uses TypeLists and CRTP to attribute different ids for the listed types.&lt;/p&gt;

&lt;h2&gt;
  
  
  A solution:
&lt;/h2&gt;

&lt;p&gt;First, let's define our TypeList (create a file called TypeList.h):&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;

&lt;span class="c1"&gt;//Typelist.h&lt;/span&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;cstddef&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;id_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="nc"&gt;Ts&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TypeList&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TypeList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;public:&lt;/span&gt;
    &lt;span class="c1"&gt;//This will be useful later&lt;/span&gt;
    &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;constexpr&lt;/span&gt; &lt;span class="n"&gt;id_type&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// -1 means invalid &lt;/span&gt;
    &lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt; &lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;constexpr&lt;/span&gt; &lt;span class="n"&gt;id_type&lt;/span&gt; &lt;span class="n"&gt;index_of&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt; &lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="nc"&gt;Ts&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TypeList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Ts&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;remaining_types&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TypeList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Ts&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
    &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;constexpr&lt;/span&gt; &lt;span class="n"&gt;id_type&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;...(&lt;/span&gt;&lt;span class="n"&gt;Ts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt; &lt;span class="nc"&gt;U&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;dummy&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; 
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Helper&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;constexpr&lt;/span&gt; &lt;span class="n"&gt;id_type&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;remaining_types&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="n"&gt;index_of&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;U&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;  
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;dummy&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Helper&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dummy&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;constexpr&lt;/span&gt; &lt;span class="n"&gt;id_type&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;

  &lt;span class="c1"&gt;// Returns -1 when the type is not found&lt;/span&gt;
  &lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt; &lt;span class="nc"&gt;F&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;constexpr&lt;/span&gt; &lt;span class="n"&gt;id_type&lt;/span&gt; &lt;span class="nf"&gt;index_of&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Helper&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;::&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="p"&gt;};&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We leverage variadic templates here. The empty parameter specialization is easy (and will prove useful later). An empty type list can't return a valid id for a type as it doesn't list anything.&lt;/p&gt;

&lt;p&gt;The second specialization is not complicated either. A type id is the count of the remaining parameters. The trick here is in the function index_of(). When F and T are of the same type, the specialized struct Helper will be instantiated, thus it's value will be equal to the current type id. When different, it will query the next level for the type id. If not found, the last level is our empty specialization, which returns an invalid id.&lt;/p&gt;

&lt;p&gt;The standard doesn't allow full specialization of class templates inside other classes, but allows partial specialization, hence the use of the dummy bool parameter.&lt;/p&gt;

&lt;p&gt;It's crucial that all values and expressions are available at compile time, thus the use of constexpr (it also allows us to define the value inside the class).&lt;/p&gt;

&lt;p&gt;A nice thing about templates is that we can offer some guarantees for the user. One that I find useful is guaranteeing one id per type. If the user tries to insert the same type twice, static_assert will be triggered.&lt;/p&gt;

&lt;p&gt;Let's implement our "parameter checker" helper:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;

&lt;span class="c1"&gt;//Typelist.h&lt;/span&gt;
&lt;span class="cm"&gt;/* Headers included before */&lt;/span&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;type_traits&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;span class="cm"&gt;/* ... declarations ... */&lt;/span&gt;

&lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="nc"&gt;Ts&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HasRepeatedParameter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt; &lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="nc"&gt;Ts&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HasRepeatedParameter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Ts&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;public:&lt;/span&gt;
  &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;constexpr&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt; &lt;span class="nc"&gt;T1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;typename&lt;/span&gt; &lt;span class="nc"&gt;T2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="nc"&gt;Ts&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HasRepeatedParameter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Ts&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;public:&lt;/span&gt;
  &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;constexpr&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HasRepeatedParameter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Ts&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;::&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;HasRepeatedParameter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Ts&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;::&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt; &lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HasRepeatedParameter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;public:&lt;/span&gt;
  &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;constexpr&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;It works by instantiating recursively itself and the specializations do the job for us.&lt;/p&gt;

&lt;p&gt;Notice that it doesn't check against a qualified (const, volatile) types. It's out of the scope of this article and would add unnecessary complexity for our goal. Maybe the reader can try to tweak it to check for qualified types as an exercise.&lt;/p&gt;

&lt;p&gt;Back to our TypeList class:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;

&lt;span class="c1"&gt;//Typelist.h&lt;/span&gt;
&lt;span class="cm"&gt;/* ... Headers and declarations/definitions... */&lt;/span&gt;

&lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt; &lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="nc"&gt;Ts&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TypeList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Ts&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Here we have our check&lt;/span&gt;
    &lt;span class="k"&gt;static_assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;HasRepeatedParameter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Ts&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;::&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"TypeList can't have repeated parameters"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="cm"&gt;/* ... Definition ...*/&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;I mentioned that I have used it on my game engine Event system, so the example I'll give will be in the same line.&lt;/p&gt;

&lt;p&gt;Let's define our Event classes (create a file called Events.h):&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;

&lt;span class="c1"&gt;//Events.h&lt;/span&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"TypeList.h"&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MouseEvent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;KeyboardEvent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;JoystickEvent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;EngineEvents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TypeList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MouseEvent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;KeyboardEvent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;JoystickEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Nothing too special. We just defined our TypeList. The forward declarations above are required, but they come with something cool. If you ever need to erase one type you can substitute it for a mock type and the other ones after it will still have the same id.&lt;/p&gt;

&lt;p&gt;Still on the same file:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;

&lt;span class="c1"&gt;//Events.h&lt;/span&gt;
&lt;span class="cm"&gt;/* ... */&lt;/span&gt;
&lt;span class="c1"&gt;// Our interface&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;IEvent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;protected:&lt;/span&gt;
  &lt;span class="n"&gt;IEvent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;public:&lt;/span&gt;
  &lt;span class="k"&gt;virtual&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;IEvent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;virtual&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;id_type&lt;/span&gt; &lt;span class="n"&gt;get_id&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Here is where the magic happens.&lt;/span&gt;
&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt; &lt;span class="nc"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EngineEvent&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;IEvent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;static_assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EngineEvents&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;index_of&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Event&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Event not at the EngineEvents list"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;EngineEvent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;virtual&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;EngineEvent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Incorrect inheritance will cause the compilation to fail, thus avoiding two events with the same id.&lt;/span&gt;
  &lt;span class="k"&gt;friend&lt;/span&gt; &lt;span class="n"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;public:&lt;/span&gt;

  &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;id_type&lt;/span&gt; &lt;span class="n"&gt;get_id&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;constexpr&lt;/span&gt; &lt;span class="n"&gt;id_type&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;EngineEvents&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;index_of&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Event&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;//Our different Events.&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MouseEvent&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;EngineEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MouseEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;public:&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;do_mouse_event_stuff&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"Doing MouseEvent stuff&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;KeyboardEvent&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;EngineEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;KeyboardEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;public:&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;do_keyboard_event_stuff&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"Doing KeyboardEvent stuff&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;JoystickEvent&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;EngineEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;JoystickEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;public:&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;do_joystick_event_stuff&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"Doing JoystickEvent stuff&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The class IEvent is the interface. A const reference to a IEvent is what our handler function will have as a parameter, thus not knowing anything beforehand about the object.&lt;/p&gt;

&lt;p&gt;The template class EngineEvent is where the magic happens. It defines an id value which is simply the index of our Event type on the EngineEvents list. This value will be available on our Event classes, as they will inherit from it. Note that in case a given event is not listed on the EngineEvents list a static_assert will be triggered, failing compilation.&lt;/p&gt;

&lt;p&gt;The remaining classes are our Event classes. They simply inherit from EngineEvent giving themselves as a template parameter (CRTP).&lt;/p&gt;

&lt;h2&gt;
  
  
  Usage:
&lt;/h2&gt;

&lt;p&gt;Now define a file called main.cpp with the following content:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;

&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;"Events.h"&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;handle_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;IEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;switch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_id&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;MouseEvent&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;static_cast&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;MouseEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;do_mouse_event_stuff&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;KeyboardEvent&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;static_cast&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;KeyboardEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;do_keyboard_event_stuff&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;JoystickEvent&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;static_cast&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;JoystickEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;do_joystick_event_stuff&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;default:&lt;/span&gt;
      &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"Event not recognized.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;MouseEvent&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;KeyboardEvent&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;JoystickEvent&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="n"&gt;handle_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;handle_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;handle_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If you did everything right you should have the following output:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ff2qccuflk33kx3pz01rj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ff2qccuflk33kx3pz01rj.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion:
&lt;/h2&gt;

&lt;p&gt;This is just one of the many possible solutions for the given problem. I like it because it is simple, doesn't introduce dependencies and is less prone to errors than Enums (different values for the same type being the main one).&lt;/p&gt;

&lt;p&gt;The full code is available at &lt;a href="https://github.com/heliobatimarqui/CompileTimeTypeID" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It's worthy noting that I tested it on G++ version 10.2.1 with the option -std=c++11. &lt;/p&gt;

&lt;p&gt;I hope you that you enjoyed it and learned something today. This is my first time posting something related to programming, so any feedback (positive or negative) would be really appreciated. Thank you!&lt;/p&gt;

</description>
      <category>cpp</category>
      <category>templates</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
