| Thread overview | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
January 03, 2015 Constant template arguments | ||||
|---|---|---|---|---|
| ||||
This doesn't compile because T is const(int) so you can't modify the arguments a and b, despite they are values:
void foo(T)(T a, T b) {
a = b;
b = a;
}
void main() {
const int x, y;
foo(x, y);
}
To make that code work I'd like to write something like this:
void foo(T)(Deconst!T a, Deconst!T b) {
Or this:
void foo(T)(@deconst T a, @deconst T b) {
Bye,
bearophile
| ||||
January 03, 2015 Re: Constant template arguments | ||||
|---|---|---|---|---|
| ||||
Posted in reply to bearophile | On Saturday, 3 January 2015 at 12:25:36 UTC, bearophile wrote:
> This doesn't compile because T is const(int) so you can't modify the arguments a and b, despite they are values:
>
>
> void foo(T)(T a, T b) {
> a = b;
> b = a;
> }
> void main() {
> const int x, y;
> foo(x, y);
> }
>
>
> To make that code work I'd like to write something like this:
>
> void foo(T)(Deconst!T a, Deconst!T b) {
>
> Or this:
>
> void foo(T)(@deconst T a, @deconst T b) {
>
> Bye,
> bearophile
Like Unqual!T?
| |||
January 03, 2015 Re: Constant template arguments | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Tobias Pankrath | Tobias Pankrath:
> Like Unqual!T?
It doesn't seem to work:
void foo(T)(Unqual!T a, Unqual!T b) {
a = b;
b = a;
}
void main() {
const int x, y;
foo(x, y);
}
Bye,
bearophile
| |||
January 03, 2015 Re: Constant template arguments | ||||
|---|---|---|---|---|
| ||||
Posted in reply to bearophile | > void foo(T)(Unqual!T a, Unqual!T b) {
> a = b;
> b = a;
> }
> void main() {
> const int x, y;
> foo(x, y);
> }
Missing line:
import std.traits: Unqual;
Bye,
bearophile
| |||
January 03, 2015 Re: Constant template arguments | ||||
|---|---|---|---|---|
| ||||
Posted in reply to bearophile | On Saturday, 3 January 2015 at 12:45:47 UTC, bearophile wrote:
>> void foo(T)(Unqual!T a, Unqual!T b) {
>> a = b;
>> b = a;
>> }
>> void main() {
>> const int x, y;
>> foo(x, y);
>> }
>
> Missing line:
>
> import std.traits: Unqual;
>
> Bye,
> bearophile
Wouldn't it be better to do this at the call site anyway? Just use a simple function.
Unqual!T unconst(T)(T val)
if (isScalarType!T)
{
return val;
}
void foo(T)(T a, T b)
{
a = b;
b = a;
}
void main()
{
const int x, y;
foo(x.unconst, y.unconst);
}
| |||
January 03, 2015 Re: Constant template arguments | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Meta | Meta:
> Wouldn't it be better to do this at the call site anyway? Just use a simple function.
>
> Unqual!T unconst(T)(T val)
> if (isScalarType!T)
> {
> return val;
> }
>
> void foo(T)(T a, T b)
> {
> a = b;
> b = a;
> }
>
> void main()
> {
> const int x, y;
> foo(x.unconst, y.unconst);
> }
That's an option. Currently Phobos doesn't use that strategy, but adds a recursive call, like in std.numeric.gcd:
T gcd(T)(T a, T b) {
static if (is(T == const) || is(T == immutable)) {
return gcd!(Unqual!T)(a, b);
} else {
static if (T.min < 0) {
//enforce(a >= 0 && b >=0);
assert(a >= 0 && b >=0);
} while (b) {
auto t = b;
b = a % b;
a = t;
}
return a;
}
}
I don't know what's better, but regular functions are able to "strip away" the const/immutable of their input values, so perhaps we should have a mean to do the same with template functions (and not at the call site) without the need of recursive calls like that one and without creating mutable local values like this:
Unqual!T mutableA = a, mutableB = b;
Bye,
bearophile
| |||
January 03, 2015 Re: Constant template arguments | ||||
|---|---|---|---|---|
| ||||
Posted in reply to bearophile | In C++ head const is stripped for ifti, but we can't do that in general in D due to transitivity. I'd like for it to happen when it can though, particularly for scalar types. | |||
January 04, 2015 Re: Constant template arguments | ||||
|---|---|---|---|---|
| ||||
Posted in reply to bearophile | On 3 January 2015 at 22:25, bearophile via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
> This doesn't compile because T is const(int) so you can't modify the arguments a and b, despite they are values:
>
>
> void foo(T)(T a, T b) {
> a = b;
> b = a;
> }
> void main() {
> const int x, y;
> foo(x, y);
> }
>
>
> To make that code work I'd like to write something like this:
>
> void foo(T)(Deconst!T a, Deconst!T b) {
>
> Or this:
>
> void foo(T)(@deconst T a, @deconst T b) {
>
> Bye,
> bearophile
I kinda feel something like this ought to work, but I can kinda see why it doesn't...
void foo(T = Unqual!U, U)(T a, T b);
Thing is, it perceives that 'T' as typed by the argument received *is* T, but it's not; T is already assigned a type. It would need to see that T is a function of U which is unknown (available to be inferred), and to forward the incoming type to U, such that T's function can be applied to it.
...yeah, it would need to transfer the type received to U, because T's type is already assigned as an explicit function of unknown U.
I'm not sure if that made sense, but I can visualise the process. I'm sure it *could* work, but would it be sturdy?
I've run into this many times in the past too... never really thought on it whether it's a problem that could actually be solved.
| |||
January 04, 2015 Re: Constant template arguments | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Manu | On Sunday, 4 January 2015 at 01:34:51 UTC, Manu via Digitalmars-d wrote:
> I kinda feel something like this ought to work, but I can kinda see
> why it doesn't...
>
> void foo(T = Unqual!U, U)(T a, T b);
>
> Thing is, it perceives that 'T' as typed by the argument received *is*
> T, but it's not; T is already assigned a type. It would need to see
> that T is a function of U which is unknown (available to be inferred),
> and to forward the incoming type to U, such that T's function can be
> applied to it.
>
> ...yeah, it would need to transfer the type received to U, because T's
> type is already assigned as an explicit function of unknown U.
>
> I'm not sure if that made sense, but I can visualise the process. I'm
> sure it *could* work, but would it be sturdy?
>
> I've run into this many times in the past too... never really thought
> on it whether it's a problem that could actually be solved.
This works for mutable, const, and immutable scalar types.
import std.traits;
U fun(T: const(U), U)(T val)
if (isScalarType!T)
{
return val;
}
void main()
{
const int n = 10;
static assert(is(typeof(n.fun) == int));
int m = 10;
static assert(is(typeof(m.fun) == int));
immutable int x = 10;
static assert(is(typeof(x.fun) == int));
}
| |||
January 04, 2015 Re: Constant template arguments | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Manu | Manu:
> I've run into this many times in the past too... never really thought
> on it whether it's a problem that could actually be solved.
Sometimes one way to realize you have a problem worth trying to solve is to push your mind sideways to a more naive state (in my original post in this thread I was in that state).
Sometimes this is useful even when you search for a solution: the word "ingenuity" in modern Italian sounds a lot like "essere ingenuo", that means something like "being unsophisticated" in English.
Bye,
bearophile
| |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply