Thread overview
default values depending on type of template variable
Sep 11, 2019
berni
Sep 11, 2019
Simen Kjærås
Sep 11, 2019
Ali Çehreli
Sep 11, 2019
berni
September 11, 2019
I'd like to write a template, that takes a different default value depending on the type of a variable. I tried this, but it doesn't work:

>void main()
>{
>    double a = 1e-8;
>    double b = 1e-10;
>    float c = 1e-4;
>    float d = 1e-6;
>
>    assert(!test(a));
>    assert(test(b));
>    assert(!test(c));
>    assert(test(d));
>}
> 
>auto test(T, U)(T value, U limit=1e-9)
>{
>    return value<limit;
>}
>
>auto test(T:float)(T value)
>{
>    return test(value, 1e-5);
>}

Although being called with a double in the first two tests, the second overload is always used and therefore the first test fails. And without this overload, the last test obviously doesn't pass.

Is there a way, to provide default values for template parameters depending on the type of an other parameter?
September 11, 2019
On Wednesday, 11 September 2019 at 08:35:02 UTC, berni wrote:
> I'd like to write a template, that takes a different default value depending on the type of a variable. I tried this, but it doesn't work:
>
>>void main()
>>{
>>    double a = 1e-8;
>>    double b = 1e-10;
>>    float c = 1e-4;
>>    float d = 1e-6;
>>
>>    assert(!test(a));
>>    assert(test(b));
>>    assert(!test(c));
>>    assert(test(d));
>>}
>> 
>>auto test(T, U)(T value, U limit=1e-9)
>>{
>>    return value<limit;
>>}
>>
>>auto test(T:float)(T value)
>>{
>>    return test(value, 1e-5);
>>}
>
> Although being called with a double in the first two tests, the second overload is always used and therefore the first test fails. And without this overload, the last test obviously doesn't pass.
>
> Is there a way, to provide default values for template parameters depending on the type of an other parameter?

unittest
{
    double a = 1e-8;
    double b = 1e-10;
    float c = 1e-4;
    float d = 1e-6;

    assert(!test(a));
    assert(test(b));
    assert(!test(c));
    assert(test(d));
}


auto test(T, U)(T value, U limit = limit!T) {
    return value < limit;
}

// Solution 1:
template limit(T) {
    static if (is(T == float)) {
        enum limit = 1e-5;
    } else {
        enum limit = 1e-9;
    }
}

// Solution 2:
enum limit(T : float)  = 1e-5;
enum limit(T : double) = 1e-9;

With some tricks this can also be inlined:

enum If(bool b, T...) = T[b ? 0 : 1];
auto test(T, U)(T value, U limit = If!(is(T == float), 1e-5, 1e-9)) {
    return value < limit;
}

--
  Simen
September 11, 2019
On 09/11/2019 01:35 AM, berni wrote:
> I'd like to write a template, that takes a different default value depending on the type of a variable.

Like this?

import std.stdio;

void main()
{
  double a = 1e-8;
  double b = 1e-10;
  float c = 1e-4;
  float d = 1e-6;

  assert(!test(a));
  assert(test(b));
  assert(!test(c));
  assert(test(d));
}

template DefaultFor(T) {
  static if (is (T == float)) {
    enum DefaultFor = 1e-5;

  } else static if (is (T == double)) {
    enum DefaultFor = 1e-9;

  } else {
    import std.string;
    static assert (false, format!"%s not supported"(T.stringof));
  }
}

auto test(T, U)(T value, U limit=DefaultFor!T)
{
  writefln!"%s: %s(%s)"(T.stringof, U.stringof, limit);
  return value<limit;
}

Ali
September 11, 2019
On Wednesday, 11 September 2019 at 09:05:47 UTC, Ali Çehreli wrote:
> Like this?

Yet an other template! That's great! :-)