title: Constexpr CRTP destructor
body: <p>I created the <code>constexpr</code> version of the Curiously Recurring Template Pattern and all seem to work as expected, except the destructor who &quot;under normal circumstances&quot; should be marked as <code>virtual</code>. As I can understand, <code>virtual</code> is the vital enemy of <code>constexpr</code>.</p>
  <p>In my example I implemented two interfaces with no data-members. Is it correct in the general case (with data-members) to let <code>virtual ~Crtp() = default;</code>, <code>virtual ~FeatureNamesInterface() = default;</code> and <code>virtual ~FeatureValuesInterface() = default;</code> commented out and let the compiler to define the destructors? Does this approach have a memory leak? Is it a better approach to make them protected? Any other solution that work with constexpr would be welcome!</p>
  <p>The interface code look like this</p>
  <pre><code>namespace lib
  {
      template &lt;typename Derived, template&lt;typename&gt; class CrtpType&gt;
      struct Crtp
      {
          //virtual ~Crtp() = default;
          [[nodiscard]] Derived&amp; child() noexcept { return static_cast&lt;Derived&amp;&gt;(*this); }
          [[nodiscard]] constexpr Derived const&amp; child() const noexcept { return static_cast&lt;const Derived&amp;&gt;(*this); }
      private:
          constexpr Crtp() = default;
          friend CrtpType&lt;Derived&gt;;
      };
  
      template&lt;typename Derived&gt;
      struct FeatureNamesInterface : Crtp&lt;Derived, FeatureNamesInterface&gt;
      {
          constexpr FeatureNamesInterface() = default;
          //virtual ~FeatureNamesInterface() = default;
          [[nodiscard]] constexpr auto&amp; GetFeatureNames() const noexcept { return Crtp&lt;Derived, FeatureNamesInterface&gt;::child().GetNames(); }
      };
  
      template&lt;typename Derived&gt;
      struct FeatureDataInterface : Crtp&lt;Derived, FeatureDataInterface&gt;
      {
          constexpr FeatureDataInterface() = default;
          //virtual ~FeatureValuesInterface() = default;
          [[nodiscard]] constexpr auto GetFeatureData() const { return Crtp&lt;Derived, FeatureDataInterface&gt;::child()(); }
      };
  }
  </code></pre>
  <p>And the implementation of the two sample classes look like this</p>
  <pre><code>namespace impl
  {
      class ChildOne final : public lib::FeatureNamesInterface&lt;ChildOne&gt;, public lib::FeatureDataInterface&lt;ChildOne&gt;
      {
          static constexpr std::array mNames{&quot;X&quot;sv, &quot;Y&quot;sv, &quot;Z&quot;sv};
      public:
          constexpr ChildOne() : FeatureNamesInterface(), FeatureDataInterface() {}
          ~ChildOne() = default;
          
          [[nodiscard]] constexpr auto&amp; GetNames() const noexcept { return mNames; }
          
          [[nodiscard]] constexpr auto operator()() const noexcept
          {
              std::array&lt;std::pair&lt;std::string_view, double&gt;, mNames.size()&gt; data;
              double value = 1.0;
              for (std::size_t i = 0; const auto&amp; name : mNames)
                  data[i++] = {name, value++};
  
              return data;
          }
      };
  
      class ChildTwo final : public lib::FeatureNamesInterface&lt;ChildTwo&gt;, public lib::FeatureDataInterface&lt;ChildTwo&gt;
      {
          static constexpr std::array mNames{&quot;A&quot;sv, &quot;B&quot;sv, &quot;C&quot;sv, &quot;D&quot;sv, &quot;E&quot;sv, &quot;F&quot;sv};
      public:
          constexpr ChildTwo() : FeatureNamesInterface(), FeatureDataInterface() {}
          ~ChildTwo() = default;
          
          [[nodiscard]] constexpr auto&amp; GetNames() const noexcept { return mNames; }
  
          [[nodiscard]] constexpr auto operator()() const noexcept
          {
              std::array&lt;std::pair&lt;std::string_view, double&gt;, mNames.size()&gt; data;
              double value = 4.0;
              for (std::size_t i = 0; const auto&amp; name : mNames)
                  data[i++] = {name, value++};
  
              return data;
          }
      };
  }
  </code></pre>
  <p>The full example can be found <a href="https://godbolt.org/z/ezerYYe4P" rel="nofollow noreferrer">here</a>.</p>