How to specify a template that uses unqualified type, like any normal function

Steven Schveighoffer via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Mon Aug 14 08:20:28 PDT 2017


On 8/14/17 9:48 AM, Dominikus Dittes Scherkl wrote:
> if I use fixed-type functions, I can do the following:
> 
> uint foo(uint n)
> {
>     ++n; // modify n - as this function has received a copy of n, this 
> is always possible
>     return 42;
> }
> 
> uint bar(const uint n)
> {
>     assert(foo(n)==42);
>     return 17;
> }
> 
> void main()
> {
>     bar(3);
> }
> 
> 
> But if I try the same with a template parameter, it doesn't work:
> 
> import std.traits; // Unqual
> 
> uint foo(T)(Unqual!T n) // first try
> {
>     ++n; // modify should be possible
>     return 42;
> }
> 
> uint foo2(T)(T n) // second try
> {
>     ++n; // modify fails, as T is const
>     return 42;
> }
> 
> uint bar(T)(const T n)
> {
>     assert(foo(n)==42u); // cannot deduce arguments - why?!?
>     assert(foo2(n)==42u); // here it can deduce the arguments, but the 
> function cannot modify n
>     return 17;
> }
> 
> void main()
> {
>     bar(3);
> }
> 
> Any ideas what I need to do to make this work?

This isn't exactly supported. Implicit Function Template Instantiation 
(IFTI) will deduce the parameters to be the types that you pass in. You 
can't deduce them and then change the parameter types. This is a 
limitation of IFTI that I have struggled with in the past.

What you can do, is:

auto foo(T)(T n) if (is(T == Unqual!T))
{
    // normal implementation
}

auto foo(T)(T n) if (!is(T == Unqual!T) && isImplicitlyConvertible!(T, 
Unqual!T))
{
    return foo!(Unqual!T)(n);
}

Hopefully the inliner cuts out the extra call.

-Steve


More information about the Digitalmars-d-learn mailing list