Phobos 3 Discussion Notes - 02-01-2024
jmh530
john.michael.hall at gmail.com
Mon Feb 12 18:13:45 UTC 2024
On Monday, 12 February 2024 at 17:00:01 UTC, Atila Neves wrote:
> On Wednesday, 7 February 2024 at 21:26:51 UTC, jmh530 wrote:
>> On Wednesday, 7 February 2024 at 10:10:27 UTC, Atila Neves
>> wrote:
>>> [snip]
>>>
>>> The problem with this approach, as C++ found out, is that
>>> `Vector!(int, MyAlloc)` is a different type from
>>> `Vector!(int, YourAlloc)`. The way I got around that is by
>>> defaulting to a global allocator. This has its drawbacks as
>>> well of course, because now everything is a virtual call.
>>
>> If you need to allocate or deallocate, then it's useful to
>> treat them as separate types. Otherwise it's not.
>
> alias MyVec = Vector(MyType, Mallocator);
> void fun(MyVec vec) {
> // just before the curly brace, the elements and
> storage for them get deallocated.
> }
I assume you mean `alias MyVec = Vector!(MyType, Mallocator);`.
I'm not completely sure I'm getting to the heart of what you're
saying since your post is a bit sparse...but I'm doing my best.
Your `fun` function only works for `MyVec`, which depends on
`MyType` and `Mallocator`. It isn't general across either types
or allocators. It's kind of the essence of your complaint about
C++ and treating `Vector!(int, MyAlloc)` and `Vector!(int,
YourAlloc)` as different types, except you are pushing all the
work downstream to functions. In other words, you have to have
separate `fun` for all the different types and allocators you
pass, and then have different allocation strategies for each.
Multiply that across all the other functions.
If all the allocators are consistent with the interface from
`std.experimental.allocator`, then you might be able to make the
allocation more general. But, it becomes frustrating to rely on
template aliases. The compiler can't see through them due to
issue 1807 [1]. The more general approach is to use template
constraints (see example below). The problem with the template
constraint approach is that it leads to template bloat, which is
why I suggested the `alias this` approach above.
Another approach would be to pass the allocator to the function
instead of making it part of the type. The problem with this is
that for some allocators you need to know what did the allocating
in order to free it safely.
```d
import std.stdio;
struct Vector(T, U) { T x; U y;}
alias MyVec = Vector!(double, int);
void fun(MyVec vec)
{
writeln("works");
}
alias MyVec2(T) = Vector!(T, int);
void fun2(T)(MyVec2!T vec)
{
writeln("works2");
}
void fun3(T)(T vec)
if (is(T : Vector!(U, int), U))
{
writeln("works3");
}
void main() {
MyVec vec = MyVec(1.0, 1);
fun(vec); // prints works
//fun2(vec); //error
fun2!double(vec); // prints works2
fun3(vec); // prints works3
}
```
[1] https://issues.dlang.org/show_bug.cgi?id=1807
More information about the Digitalmars-d
mailing list