Note that there are some explanatory texts on larger screens.

plurals
  1. POAny way to make parameterized user defined literals?
    primarykey
    data
    text
    <p>A little while ago I had an idea about "parameterized" user-defined literals and was wondering if there is any way to do this in the current C++ standard.</p> <p>Basically, the idea is to have a user-defined literal whose behaviour can be tweaked according to some parameters. As a simple example, I chose a "fixed-point" literal which turns a floating-point number into an integer; the parameter is the precision in terms of the number of decimal places.</p> <p>This is just an exercise for now, since I'm not sure how or if this would be useful in a real application.</p> <p>My first idea went something like this:</p> <pre class="lang-c prettyprint-override"><code>namespace fp_impl { constexpr int floor(long double n) { return n; } constexpr int pow10(int exp) { return exp == 0 ? 1 : 10 * pow10(exp - 1); } template&lt;int i&gt; constexpr int fixed_point(long double n) { return floor(n * pow10(i)); } namespace fp2 { constexpr int operator"" _fp (long double n) { return fixed_point&lt;2&gt;(n); } } namespace fp4 { constexpr int operator"" _fp (long double n) { return fixed_point&lt;4&gt;(n); } } } template&lt;int prec&gt; struct fp; template&lt;&gt; struct fp&lt;2&gt; { namespace lit = fp2; }; template&lt;&gt; struct fp&lt;4&gt; { namespace lit = fp4; }; int main() { { using namespace fp&lt;2&gt;::lit; std::cout &lt;&lt; 5.421_fp &lt;&lt; std::endl; // should output 542 } { using namespace fp&lt;4&gt;::lit; std::cout &lt;&lt; 5.421_fp &lt;&lt; std::endl; // should output 54210 } } </code></pre> <p>However, it doesn't compile because namespace aliases are not permitted at class scope. (It also has a problem with requiring you t manually define every version of <code>operator"" _fp</code>.) So I decided to try something with macros:</p> <pre class="lang-c prettyprint-override"><code>namespace fp { namespace detail { constexpr int floor(long double n) { return n; } constexpr int pow10(int exp) { return exp == 0 ? 1 : 10 * pow10(exp - 1); } template&lt;int i&gt; constexpr int fixed_point(long double n) { return floor(n * pow10(i)); } } } #define SPEC(i) \ namespace fp { \ namespace precision##i { \ constexpr int operator"" _fp(long double n) { \ return fp::detail::fixed_point&lt;i&gt;(n); \ } \ } \ } SPEC(2); SPEC(4); #undef SPEC #define fp_precision(i) namespace fp::precision##i int main() { { using fp_precision(2); std::cout &lt;&lt; 5.421_fp &lt;&lt; std::endl; } { using fp_precision(4); std::cout &lt;&lt; 5.421_fp &lt;&lt; std::endl; } } </code></pre> <p>This works, though it still has the requirement of using the <code>SPEC()</code> macro for every precision you ever want to use. Of course, some preprocessor trickery could be used to do this for every value from, say, 0 to 100, but I'm wondering if there could be anything more like a template solution, where each one is instantiated as it is needed. I had a vague idea of using an operator"" declared as a friend function in a template class, though I suspect that won't work either.</p> <p>As a note, I did try <code>template&lt;int i&gt; constexpr int operator"" _fp(long double n)</code>, but it seems this is not an allowed declaration of a literal operator.</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.
 

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