Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p><strong>Short answer</strong> </p> <p>If using <code>std::common_type</code> as provided by the standard library is absolutely required, there's no better way other than the 3 alternatives you observed yourself. If a user defined <code>common_type</code> be considered acceptable, then you can achieve what you want as shown below.</p> <hr> <p><strong>Long Answer</strong></p> <p>You are right when you say <code>std::common_type&lt;unsigned [long [long]] int, [long [long]] int&gt;::type</code> will yield <code>unsigned [long [long]]</code>. However, since the <code>common_ type</code> of any expression involving <code>ranged_integer</code> is itself a <code>ranged_integer</code> and given that your specializations involving <code>ranged_integer</code> correctly infer the ranges, there's only a problem if the pairwise <code>common_type</code> of the types preceding <code>[long [long]] unsigned</code> yields <code>[long [long]] int</code>.T̶h̶a̶t̶ ̶l̶e̶a̶v̶e̶s̶ ̶u̶s̶ ̶o̶n̶l̶y̶ ̶s̶i̶x̶ ̶c̶a̶s̶e̶s̶ ̶w̶e̶ ̶h̶a̶v̶e̶ ̶t̶o̶ ̶w̶o̶r̶k̶a̶r̶o̶u̶n̶d̶,̶ ̶n̶a̶m̶e̶l̶y̶ ̶<code>̶s̶t̶d̶:̶:̶c̶o̶m̶m̶o̶n̶_̶t̶y̶p̶e̶&lt;̶u̶n̶s̶i̶g̶n̶e̶d̶ ̶[̶l̶o̶n̶g̶ ̶[̶l̶o̶n̶g̶]̶]̶ ̶i̶n̶t̶,̶ ̶[̶l̶o̶n̶g̶ ̶[̶l̶o̶n̶g̶]̶]̶ ̶i̶n̶t̶&gt;̶:̶:̶t̶y̶p̶e̶</code>̶ ̶a̶n̶d̶ ̶t̶h̶e̶i̶r̶ ̶o̶r̶d̶e̶r̶i̶n̶g̶ ̶p̶e̶r̶m̶u̶t̶a̶t̶i̶o̶n̶s̶.̶ ̶(̶I̶'̶m̶ ̶i̶g̶n̶o̶r̶i̶n̶g̶ ̶t̶h̶e̶ ̶f̶i̶x̶e̶d̶ ̶w̶i̶d̶t̶h̶ ̶t̶y̶p̶e̶s̶ ̶h̶e̶r̶e̶,̶ ̶b̶u̶t̶ ̶t̶h̶e̶ ̶e̶x̶t̶e̶n̶d̶i̶n̶g̶ ̶t̶h̶e̶ ̶i̶d̶e̶a̶ ̶t̶o̶ ̶c̶o̶n̶s̶i̶d̶e̶r̶ ̶t̶h̶e̶m̶ ̶s̶h̶o̶u̶l̶d̶ ̶b̶e̶ ̶s̶t̶r̶a̶i̶g̶h̶t̶f̶o̶r̶w̶a̶r̶d̶)̶</p> <p>W̶e̶ ̶c̶a̶n̶ ̶a̶c̶h̶i̶e̶v̶e̶ ̶t̶h̶a̶t̶ ̶b̶y̶ ̶a̶g̶a̶i̶n̶ ̶p̶r̶o̶v̶i̶d̶i̶n̶g̶ ̶e̶x̶p̶l̶i̶c̶i̶t̶ ̶s̶p̶e̶c̶i̶a̶l̶i̶z̶a̶t̶i̶o̶n̶s̶:̶</p> <p><strong>In fact we can't according to</strong> <a href="http://open-std.org/JTC1/SC22/WG21/docs/papers/2012/n3485.pdf" rel="nofollow">n3485</a></p> <p><strong>[meta.type.synop] Paragraph 1</strong></p> <p><em>"The behavior of a program that adds specializations for any of the class templates defined in this subclause [<code>template &lt;class... T&gt; common_type</code> included] is undefined unless otherwise specified."</em></p> <p><strong>[meta.trans.other] Table 57</strong></p> <p><em>[...] A program may specialize this trait [<code>template &lt;class... T&gt; common_type</code>] if at least one template parameter in the specialization is a user-defined type. [...]</em>"</p> <p>That implies that <strong>there's no valid way of overwriting the behavior for <code>std::common_type&lt;unsigned [long [long]] int, [long [long]] int&gt;::type</code></strong>, it is required by the standard to always yield <code>unsigned [long [long]] int</code> as pointed out before. </p> <hr> <p><strong>Alternative to <code>std::common_type</code></strong></p> <p>An alternative to overcome the limitations of <code>std::common_type</code> when applied to primitive integral types, is to define a custom <code>common_type</code>.</p> <p>Assuming <code>ranged_integer</code> to be defined as follows.</p> <pre><code>template&lt;typename T, T min, T max&gt; struct basic_ranged_integer; template&lt;std::intmax_t min, std::intmax_t max&gt; using ranged_integer = basic_ranged_integer&lt;std::intmax_t, min, max&gt;; </code></pre> <p>A custom <code>common_type</code> could be defined as follows. </p> <p>First the left recursion:</p> <pre><code>template&lt;typename... T&gt; struct common_type; template&lt;typename T, typename U, typename... V&gt; struct common_type&lt;T, U, V...&gt; : common_type&lt;typename common_type&lt;T, U&gt;::type, V...&gt; //left recursion {}; </code></pre> <p>Now the specializations involving <code>basic_ranged_integer</code>.</p> <pre><code>//two basic_ranged_integer template&lt;typename T, T minT, T maxT, typename U, U minU, U maxU&gt; struct common_type&lt;basic_ranged_integer&lt;T, minT, maxT&gt;, basic_ranged_integer&lt;U, minU, maxU&gt;&gt; { //gory details go here }; //basic_ranged_integer mixed with primitive integer types //forwards to the case involving two basic_ranged_integer template&lt;typename T, T minT, T maxT, typename U&gt; struct common_type&lt;basic_ranged_integer&lt;T, minT, maxT&gt;, U&gt; : common_type &lt; basic_ranged_integer&lt;T, minT, maxT&gt;, typename make_ranged_integer&lt;U&gt;::type &gt; {}; template&lt;typename T, typename U, U minU, U maxU&gt; struct common_type&lt;T, basic_ranged_integer&lt;U, minU, maxU&gt;&gt; : common_type &lt; typename make_ranged_integer&lt;T&gt;::type, basic_ranged_integer&lt;U, minU, maxU&gt; &gt; {}; </code></pre> <p>And finally the specializations involving a combination of signed and unsigned primitive integers.</p> <pre><code>//base case: forwards to the satandard library template&lt;typename T&gt; struct common_type&lt;T&gt; : std::common_type&lt;T&gt; {}; template&lt;typename T, typename U&gt; struct common_type&lt;T, U&gt; { static constexpr bool signed_xor = std::is_signed&lt;T&gt;{} xor std::is_signed&lt;U&gt;{}; //base case: forwards to the satandard library template&lt;bool b = signed_xor, typename = void&gt; struct helper : std::common_type&lt;T, U&gt; {}; //mixed signed/unsigned: forwards to the case involving two basic_ranged_integer template&lt;typename _ &gt; struct helper&lt;true, _&gt; : common_type&lt;typename make_ranged_integer&lt;T&gt;::type, typename make_ranged_integer&lt;U&gt;::type&gt; {}; using type = typename helper&lt;&gt;::type; }; </code></pre> <p>In the above <code>make_ranged_integer</code> is expected to take a primitive integer type and define <code>type</code> to be the desired corresponding <code>basic_ranged_integer</code>.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload