July 07, 2013
Am Sat, 6 Jul 2013 20:24:41 +1000
schrieb Manu <turkeyman@gmail.com>:

> On 6 July 2013 18:23, Namespace <rswhite4@googlemail.com> wrote:
> 
> > That doesn't do what I want at all. The signature is still f(T) not
> >> f(Unqual!T).
> >>
> >
> > For non-const, const and immutable inout would do it.
> >
> > void f(T)(inout T var)
> >
> 
> Not if there's more than 1 argument, and 'inout T' is still not 'T'.

Hey, inout looks like a neat solution! And it only creates one template instance no matter how many arguments of type inout(T) you use!

-- 
Marco

July 07, 2013
On Sunday, 7 July 2013 at 11:07:44 UTC, Marco Leise wrote:
> Am Sat, 6 Jul 2013 20:24:41 +1000
> schrieb Manu <turkeyman@gmail.com>:
>
>> On 6 July 2013 18:23, Namespace <rswhite4@googlemail.com> wrote:
>> 
>> > That doesn't do what I want at all. The signature is still f(T) not
>> >> f(Unqual!T).
>> >>
>> >
>> > For non-const, const and immutable inout would do it.
>> >
>> > void f(T)(inout T var)
>> >
>> 
>> Not if there's more than 1 argument, and 'inout T' is still not 'T'.
>
> Hey, inout looks like a neat solution! And it only creates one
> template instance no matter how many arguments of type
> inout(T) you use!

const would have the same effect:

void f(T)(const T var) { ... }

...but then you can't mutate var.
July 07, 2013
Am Sun, 7 Jul 2013 00:06:26 +1000
schrieb Manu <turkeyman@gmail.com>:

> On 6 July 2013 22:27, Namespace <rswhite4@googlemail.com> wrote:
> 
> > The way that makes the most sense to me is:
> >>
> >> void f(T)(Unqual!T t) {}
> >>
> >> Given an immutable(T) for instance that I want to call with, it would
> >> instantiate the template with the signature void f(T), and then attempt to
> >> call it with the immutable(T). If immutable(T) is not convertible to the
> >> argument T, then it would produce a compile error as if attempting to call
> >> any such function that just receives T.
> >>
> >> The point here is that I want more control over the signature of the instantiated template (reduce the number of permutations generated for various calls). Template blow-out is perhaps the biggest and most well known day-to-day problem in C++, and tools like this may be very valuable to mitigate the disaster.
> >>
> >
> > It seems that your code works if you put the Template Type explicit:
> > ----
> > import std.stdio;
> > import std.traits : Unqual;
> >
> > void foo(T)(Unqual!T a) {
> >         writeln(typeof(a).stringof, " <-> ", T.stringof);
> > }
> >
> > void main() {
> >         int a;
> >         const int b;
> >         immutable int c;
> >
> >         //foo(c); /// Error
> >         foo!(typeof(a))(a);
> >         foo!(typeof(b))(b);
> >         foo!(typeof(c))(c);
> > }
> > ----
> >
> 
> Indeed, hence my point that the type deduction is the key issue here. It should be possible... maybe a bit tricky though.

If you wanted to save on template instantiations for every possible attribute combination, you are doing it wrong. Those are already 3 duplicate templates with binary identical functions foo(int a) in them, which makes me cry on the inside.

-- 
Marco

July 07, 2013
Am Sat, 06 Jul 2013 17:10:24 +0200
schrieb "Dicebot" <public@dicebot.lv>:

> On Saturday, 6 July 2013 at 15:05:51 UTC, Artur Skawina wrote:
> > ...
> 
> It is not that simple. Consider:
> 
> void f(T)(T t)
> {
>      static if (T == Unqual!T)
>      // one function body
>      else
>      // completely different one
> }
> 
> Currently every template instance is completely independent and tied to exact type. I don't know of any tool to express "group of related types" concept in D other than built-in "inout".

Hmm, this inout stuff sounds like a possible solution...

-- 
Marco

July 07, 2013
Am Sun, 07 Jul 2013 01:04:52 +0400
schrieb Dmitry Olshansky <dmitry.olsh@gmail.com>:

> I've seen an aggressive proposal back in the day to just do a shallow unqual on all aggregates passed by value.

I came to the same conclusion. If feasible, type inference
should always produce tail-const versions.
Well, Rebinable!T then for classes. ;)
It is really annoying to have value types like ints passed in
as immutable/const, just because they were at the call site.
Even for array slices arguments it's sometimes neat to be able
to shrink the passed slice to remove elements that you don't
need to process (whitespace, zeroes, ...)

-- 
Marco

July 07, 2013
Am Sat, 06 Jul 2013 17:24:23 +0200
schrieb "Dicebot" <public@dicebot.lv>:

> On Saturday, 6 July 2013 at 01:35:09 UTC, Manu wrote:
> > ...
> 
> If this is about template bloat I think much better is to address problem in general. For example, internal linkage or strict export requirements - anything that will allow to inline and completely eliminate trivial templates leaving no traces of it in final executable.

Less duplicate instantiations results in faster compile times. An area where DMD is really good and should strive to keep its pole position.

-- 
Marco

July 07, 2013
Am Sun, 07 Jul 2013 13:17:23 +0200
schrieb "TommiT" <tommitissari@hotmail.com>:

> const would have the same effect:
> 
> void f(T)(const T var) { ... }
> 
> ...but then you can't mutate var.

That doesn't handle shared.

-- 
Marco

July 07, 2013
On Sunday, 7 July 2013 at 11:59:36 UTC, Marco Leise wrote:
> Am Sun, 07 Jul 2013 13:17:23 +0200
> schrieb "TommiT" <tommitissari@hotmail.com>:
>
>> const would have the same effect:
>> 
>> void f(T)(const T var) { ... }
>> 
>> ...but then you can't mutate var.
>
> That doesn't handle shared.

That seems like a compiler bug to me.
July 07, 2013
06-Jul-2013 05:34, Manu пишет:
> Okay, so I feel like this should be possible, but I can't make it work...
> I want to use template deduction to deduce the argument type, but I want
> the function arg to be Unqual!T of the deduced type, rather than the
> verbatim type of the argument given.
>
> I've tried: void f(T : Unqual!U, U)(T a) {}
> and: void f(T)(Unqual!T a) {}

The thing is that if even if you somehow force your way past IFTI what would be generated is:

f!(const int)(int arg);
f!(immutable int)(int arg);
f!(shared int)(int arg);
f!(const shared int)(int arg);

Which IMHO falls short of desired goal.
Short of using a forwarding thunk (that you don't like, but if there was force_inline?) we'd have to hack the compiler.

>
> Ie, if called with:
>    const int x;
>    f(x);
> Then f() should be generated void f(int) rather than void f(const int).

> I don't want a million permutations of the template function for each
> combination of const/immutabe/shared/etc, which especially blows out
> when the function has 2 or more args.
>
> Note: T may only be a primitive type. Obviously const(int*) can never be
> passed to int*.




-- 
Dmitry Olshansky
July 07, 2013
On Saturday, 6 July 2013 at 18:54:16 UTC, TommiT wrote:
> He's talking about changing the semantics only on POD types, like int, struct of ints, static array of ints... only types that can implicitly convert from immutable to mutable.

Than it does not really solve anything. Have you measured how much template bloat comes from common meta-programming tools like std.algorithm and how much - from extra instances for qualified POD types? It is better to solve broad problem instead and get this special case for free, not add more special cases in a desperate attempts to contain it.