title: C++ concepts for template-values and parameter pack
body: <p>Was wondering what syntax would be the most effective/convenient for <code>concepts</code> on <code>parameters pack</code>, including <code>values template-parameters</code> when types (ou values' types) depend on each other?</p>
  <p>For instance, with the following function :</p>
  <blockquote>
  <p><code>equal_v&lt;values...&gt;</code> is true when all values are equal</p>
  </blockquote>
  <pre class="lang-cpp prettyprint-override"><code>template &lt;auto... values&gt;
  constexpr static auto equal_v = []() consteval
  {
      static_assert(sizeof...(values) &gt; 0, &quot;equal_v : no arguments&quot;);
      constexpr auto first_value = std::get&lt;0&gt;(std::tuple{values...});
      static_assert(
          (std::equality_comparable_with&lt;decltype(values), decltype(first_value)&gt; &amp;&amp; ...),
          &quot;equal_v : cannot compare values&quot;);
      return ((values == first_value) &amp;&amp; ...);
  }
  ();
  </code></pre>
  <p>I would have :</p>
  <pre class="lang-cpp prettyprint-override"><code>template &lt;typename ... Ts&gt;
  concept are_equality_comparable = requires(Ts ... values)
  {
      { 
          std::conditional_t&lt;(std::equality_comparable_with&lt;decltype(std::get&lt;0&gt;(std::tuple{values...})), decltype(values)&gt; &amp;&amp; ...), std::true_type, std::false_type&gt;{}
      } -&gt; std::same_as&lt;std::true_type&gt;;
  };
  
  template &lt;auto ... values&gt;
      requires(are_equality_comparable&lt;decltype(values)...&gt;)
  constexpr static auto equal_v = []() consteval {
      static_assert(sizeof...(values) &gt; 0, &quot;equal_v : no arguments&quot;);
      constexpr auto first_value = std::get&lt;0&gt;(std::tuple{values...});
     
      return ((values == first_value) &amp;&amp; ...); 
  }();
  </code></pre>
  <p>Which is kinda ugly, using <code>std::conditional&lt;..., std::true_type, std::false_type&gt;</code> as <code>std::same_as&lt;..., std::true_type&gt;</code> arguments.</p>
  <p>So I ends up with the following syntax, which I think is the most elegant :</p>
  <pre class="lang-cpp prettyprint-override"><code>template &lt;auto first_value, auto ... values&gt;
      requires (std::equality_comparable_with&lt;decltype(first_value), decltype(values)&gt; &amp;&amp; ...)
  constexpr static auto equal_v = []() consteval {
      return ((values == first_value) &amp;&amp; ...); 
  }();
  </code></pre>
  <p>or, with not mandatory first parameter :</p>
  <pre class="lang-cpp prettyprint-override"><code>template &lt;auto ... values&gt;
      requires (std::equality_comparable_with&lt;decltype(std::get&lt;0&gt;(std::tuple{values...})), decltype(values)&gt; &amp;&amp; ...)
  constexpr static auto equal_v = []() consteval {
      return ((values == std::get&lt;0&gt;(std::tuple{values...})) &amp;&amp; ...); 
  }();
  </code></pre>
  <p>However, as all values depends on the first one,<br />
  I did not figure out a way using such hypothetic syntax yet :</p>
  <pre class="lang-cpp prettyprint-override"><code>template &lt;auto first_value, std::equality_comparable_with&lt;decltype(first_value)&gt; ... values&gt;
  constexpr static auto equal_v = []() consteval {
      return ((values == first_value) &amp;&amp; ...); 
  }();
  </code></pre>
  <p>So, here are some points :</p>
  <ul>
  <li>Is there an elegant way to use concepts to restrict template-values's types instead of template-type-arguments?</li>
  <li>Is there a way to restrict types in a template-parameter-pack that depends on each other without modifying the function signature, without the <code>requires</code> clause?
  e.g <code>template &lt;auto ... values&gt;</code> instead of <code>template &lt;auto first_value, auto ... values&gt;</code></li>
  </ul>
  <p>[EDIT]
  As pinpointed by <a href="https://stackoverflow.com/users/5754656/artyer">artyer</a> in the comments, <code>concept auto value</code> is a valid syntax.<br />
  <em>Also, this does not work with <strong>MSVC 19.28</strong> as it results in :</em></p>
  <blockquote>
  <p>error C7601: the associated constraints are not satisfied</p>
  </blockquote>
  <p><em>nor GCC 10.2 :</em></p>
  <blockquote>
  <p>error: placeholder constraints not satisfied</p>
  </blockquote>
  <p><em>But works fine with Clang 11.0.1.</em></p>
  <pre class="lang-cpp prettyprint-override"><code>template &lt;auto first_value, std::equality_comparable_with&lt;decltype(first_value)&gt; auto ... values&gt; constexpr static auto equal_v = []() consteval {
     return ((values == first_value) &amp;&amp; ...);
  }();
  </code></pre>
  <p>[EDIT_2]</p>
  <p>In order to make <code>equal_v&lt;&gt;</code> true :</p>
  <pre class="lang-cpp prettyprint-override"><code>template &lt;auto first_value = int{}, std::equality_comparable_with&lt;decltype(first_value)&gt; auto ... values&gt;
  constexpr static auto equal_v = []() consteval {
     return ((values == first_value) &amp;&amp; ...);
  }();
  </code></pre>