On 12/12/2014 6:55 PM, Manu via Digitalmars-d wrote:
I did just give some examples, I'll repeat; auto ref fails when the
function is extern.

Don't make it extern, then.


It is also wrong that when I pass an int or float, it is passed by ref
instead of by value... that is never what I want!

If there's source to the function, it'll often be inlined which will remove the indirection.


What do you get when you take a pointer of a function with an auto-ref
arg? ...an error, because it's not actually a function!
So in a context where I'm dealing with functions and function pointers
(very, very frequent), I suddenly have something that's not a function
find it's way into my meta and I have to special-case the hell out of
it.

Why are function pointers and ints going to the same argument of a function? I thought you weren't using templates?


The solution in this case is to wrap it in a non-auto-ref shim with
the ref-ness explicitly stated in the way I expect... which is in
itself another problem, because 'ref' is not part of the type! So the
annoying de-auto-ref-ing shim must be a text mixin with some very
complex, practically unreadable, definitely unmaintainable logic
surrounding it. It's insanity on top of insanity!

I also run the invisible risk of generating 2^num_args instances of
the code for functions containing auto-ref args.

I wonder what is the need for the code that you are writing.


When I'm writing a function that's not a template, I intend, and
expect, to write a function that's _not a template_.
Templates and functions are different things. I think it's a massive
mistake to have created a way to write a template that looks nothing
like a template.

A function template is a function that takes both compile-time args and run-time args. C++ tried to make them completely different animals, when they are not. Don't think "template", think "compile-time argument to a function". I convinced Andrei to never mention "template" in his D book, as it brings forth all kinds of connotations and expectations that impede understanding what D templates actually are. I think the result was successful.


auto-ref is not, and never has been a tool I have wanted. I don't have
any use for auto-ref, and it has only proven to make an already severe
problem worse. I've tried to use it before in some instances, but it
made ref's out of int's and floats, so even in the rare potentially
useful cases, I had to reject it.

If it's a rare useful case, why is it a pervasive problem?


At the time, you introduced auto-ref as a 'solution' to an issue that
I was the primary complainant (although the solution was mainly pushed
by Andrei iirc?). I absolutely rejected it then, and said it would
have the disastrous effect of setting ref in stone, which I was
already very critical about. I reject it even more now that I have had
some experience with it.
Who was the customer that you designed it for? (It wasn't me!)
What issue was it designed to address?

I still have no idea what code you are developing that you need to send ints and function pointers to the same argument of a function template, yet you don't use function templates. Nor do I understand what pattern you need that simply must mix up ref and value parameters, and why that pattern appears pervasively in your code.


struct Tree {
    RefCount!(Tree*) left;
    RefCount!(Tree*) right;
    ...
}

... I don't think I'd ever have a use for this code.

You have no use for tree structures?


I've been using trees for a long time, and I can't imagine a situation
where each node in a tree would want to be ref counted.

You have more than one parent of a node. You never write data structures like that? dmd uses such pervasively (Type and Expression).


It sounds like a disaster for performance, and I can't imagine any
advantage it would offer?

How do you propose to manage the memory explicitly otherwise? Use a GC? :-)


I can see common cases where nodes may contain a refcounted object as
node data, but that's different than the situation you demonstrate
here.

That would fail if scope were transitive.


But there are more things than pointers which need to be protected
against escaping their scope, in particular, things that contain
pointers...

Solve it in the general case (this proposal) and RC now works.


Maybe there's a compromise. If we say scope isn't 'transitive', but it
is transitive when it comes to aggregates?

One thing I've tried very hard to make work in D is have basic types / aggregages / arrays be interchangeable.


Ie, you can apply scope to a by-val struct, and all aggregate members
have scope applied.
It is not transitive in the sense that it does not follow through
pointer members, but any such pointer members may not escape as if it
were a pointer argument alone.

This is unlike any other behaviour in D, but without that, I think
this proposal fails to suit my most common use cases.

I have no idea what your use cases are, but when you're explicitly managing memory, every damn pointer needs to be carefully evaluated as to what exactly it's pointing two and who owns it. Scope is not a magic solution to this, neither is shared_ptr, neither are Rust's annotations.

The only scheme that absolves the user of having to deal with this is - GC.

Reply via email to