Thread overview
default values depending on type of template variable
Sep 11
berni
Sep 11
berni
September 11
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
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
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
On Wednesday, 11 September 2019 at 09:05:47 UTC, Ali Çehreli wrote:
> Like this?

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