July 06, 2013 Re: Fun with templates | ||||
---|---|---|---|---|
| ||||
Posted in reply to Manu | On Saturday, 6 July 2013 at 01:35:09 UTC, Manu wrote:
> 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) {}
>
> 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*.
You could just forward to an implementation template, passing explicitly the arguments. This is kind of like the "take" function making an explicit call to "Take!T" I guess. In any case, this is what I mean.
--------
void foo(T)(T t)
{
fooImpl!(Unqual!T)(t);
}
void fooImpl(T)(T t)
{
static assert(is(Unqual!T == T));
//do it
}
void main()
{
const(int) x;
foo(x);
}
--------
This should do what you want. foo should be completly inlined away I believe. It is a tiny bit hackish, but should work. You'll generate all flavors of foo, but only Unqual'd versions of fooImpl (which is what you care about). You can also add some "isPrimitivee!T" if you want or something.
Not sure how this deals with "shared" ? In any case, you asked for "Unqual", so that's what you get ;)
|
July 06, 2013 Re: Fun with templates | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | On Saturday, 6 July 2013 at 08:42:45 UTC, monarch_dodra wrote:
> On Saturday, 6 July 2013 at 01:35:09 UTC, Manu wrote:
>> 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.
> You could just forward to an implementation template, passing explicitly the arguments.
Hum.. just realized you explicitly wanted to do this via template deduction. I'm not sure then :/ Sorry. Hope my workaround will be useful for you? Chances are you probably already had it worked out.
|
July 06, 2013 Re: Fun with templates | ||||
---|---|---|---|---|
| ||||
Posted in reply to Namespace Attachments:
| 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'.
|
July 06, 2013 Re: Fun with templates | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra Attachments:
| On 6 July 2013 18:45, monarch_dodra <monarchdodra@gmail.com> wrote:
> On Saturday, 6 July 2013 at 08:42:45 UTC, monarch_dodra wrote:
>
>> On Saturday, 6 July 2013 at 01:35:09 UTC, Manu wrote:
>>
>>> 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.
>>>
>> You could just forward to an implementation template, passing explicitly the arguments.
>>
>
> Hum.. just realized you explicitly wanted to do this via template deduction. I'm not sure then :/ Sorry. Hope my workaround will be useful for you? Chances are you probably already had it worked out.
>
Nope, still have no good idea of my own. My first 2 impulses were the best shot I had, but they didn't work.
Forwarding to an Impl template doesn't really address my problem. I still end out with bucket loads of instantiations, and double-call performance will really suffer in debug builds, which might be okay if these were big functions, but they're many trivial functions, so the cost is very high.
I'm getting the distinct feeling that what I want is not actually possible. Which I have to say, is rather surprising.
|
July 06, 2013 Re: Fun with templates | ||||
---|---|---|---|---|
| ||||
Posted in reply to Manu | On Saturday, 6 July 2013 at 10:34:04 UTC, Manu wrote:
> I'm getting the distinct feeling that what I want is not actually possible.
> Which I have to say, is rather surprising.
This seems like a defect of the language. Perhaps a new language feature is needed. Something like this:
void foo(inout T)(T t)
{
t.mutate();
}
Pass a variable of type S, const(S), or mutable(S), and the function signature becomes:
void foo(S);
And then fails if your argument cannot be converted to mutable S.
|
July 06, 2013 Re: Fun with templates | ||||
---|---|---|---|---|
| ||||
Posted in reply to TommiT | On Saturday, 6 July 2013 at 11:23:08 UTC, TommiT wrote:
> Pass a variable of type S, const(S), or mutable(S) ...
That should have been immutable(S)
|
July 06, 2013 Re: Fun with templates | ||||
---|---|---|---|---|
| ||||
Posted in reply to TommiT Attachments:
| On 6 July 2013 21:23, TommiT <tommitissari@hotmail.com> wrote:
> On Saturday, 6 July 2013 at 10:34:04 UTC, Manu wrote:
>
>> I'm getting the distinct feeling that what I want is not actually
>> possible.
>> Which I have to say, is rather surprising.
>>
>
> This seems like a defect of the language. Perhaps a new language feature is needed. Something like this:
>
> void foo(inout T)(T t)
> {
> t.mutate();
> }
>
> Pass a variable of type S, const(S), or mutable(S), and the function
> signature becomes:
>
> void foo(S);
>
> And then fails if your argument cannot be converted to mutable S.
>
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.
|
July 06, 2013 Re: Fun with templates | ||||
---|---|---|---|---|
| ||||
Posted in reply to Manu | On Saturday, 6 July 2013 at 11:35:28 UTC, Manu wrote:
> On 6 July 2013 21:23, TommiT <tommitissari@hotmail.com> wrote:
>
>> On Saturday, 6 July 2013 at 10:34:04 UTC, Manu wrote:
>>
>>> I'm getting the distinct feeling that what I want is not actually
>>> possible.
>>> Which I have to say, is rather surprising.
>>>
>>
>> This seems like a defect of the language. Perhaps a new language feature
>> is needed. Something like this:
>>
>> void foo(inout T)(T t)
>> {
>> t.mutate();
>> }
>>
>> Pass a variable of type S, const(S), or mutable(S), and the function
>> signature becomes:
>>
>> void foo(S);
>>
>> And then fails if your argument cannot be converted to mutable S.
>>
>
> The way that makes the most sense to me is:
>
> void f(T)(Unqual!T t) {}
That would look more sensible, but I don't think that's implementable if any template could be used in the place of 'Unqual'. For example:
struct Soo(T, int v)
{}
template Too(T, int x)
{
alias Too = Soo!(T, x * x - 102);
}
void foo(T, n)(Too!(T, n) var)
{}
void main()
{
Soo!(int, 42) var;
foo(var);
}
It would be pretty difficult for the compiler to figure out during the instantiation of foo that T == int and n == 12. I don't know, but I suspect it's pretty impossible to implement a compiler that could figure out those template parameters for every possible scenario.
|
July 06, 2013 Re: Fun with templates | ||||
---|---|---|---|---|
| ||||
Posted in reply to Manu | > 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);
}
----
|
July 06, 2013 Re: Fun with templates | ||||
---|---|---|---|---|
| ||||
Posted in reply to Manu | On Saturday, 6 July 2013 at 11:35:28 UTC, Manu wrote:
> The way that makes the most sense to me is:
>
> void f(T)(Unqual!T t) {}
But my syntax makes pretty much sense too:
void foo(inout T)(T var)
{
var = 42;
}
void main()
{
foo!(int)(1);
foo!(const int)(2);
foo!(immutable int)(3);
}
For all those calls to foo, the type parameter T is deduced to be int, and the function template instantiates to the signature:
void foo(int var);
The function template foo accepts int, const(int) and immutable(int) as the type parameter, because they're all convertible to inout(int).
The same kind of logic can be seen with runtime arguments, when they are qualified with something:
void bar(T)(const T var) { }
void main()
{
const int n;
bar(n);
}
Here, similarly, the type of T is deduced to be int, even though the argument passed in is const(int).
|
Copyright © 1999-2021 by the D Language Foundation