search of a workaround
monarch_dodra
monarchdodra at gmail.com
Fri Feb 8 15:10:37 PST 2013
On Friday, 8 February 2013 at 21:06:27 UTC, Namespace wrote:
> I've been thinking about the lack of rvalue references.
> Therefore, I would like to know what you think is the best
> workaround for this feature.
> I illustrate below the only (*) five solutions briefly and
> summarized.
> What do you think is the best? Which of these do you use? Or
> did I forget some possible solutions?
> I'm looking for this for small data structures, such as
> vectors, matrices, or colors.
>
> (*) In my opinion.
>
> --------
>
> struct A { }
>
> ---- Solution #1 ----
>
> // rvalues
> void foo(A a) {
> foo(a);
> }
>
> // lvalues
> void foo(ref A a) {
>
> }
>
> ----------------------------------
> Summarized: flexible, efficient but code bloat, more effort and
> bug prone:
>
> void foo(A a) {
> writeln("call no ref");
> foo(a);
> }
>
> void foo(const ref A a) {
> writeln("call ref");
> }
>
> void main() {
> foo(A());
> }
>
> -> endless loop!
>
> ---- Solution #2 ----
>
> // fuck it, copy lvalues and rvalues
> void foo(A a) {
>
> }
>
> ----------------------------------
> Summarized: flexible, no code bloat but inefficient ->
> unnecessary copies
>
> ---- Solution #3 ----
>
> // allow only lvalues
> void foo(ref A a) {
>
> }
>
> ----------------------------------
> Summarized: You have to make temporary values by yourself:
> unhandy, ugly and code bloat
>
> ---- Solution #4 ----
>
> // accept only pointers
> void foo(A* a) {
>
> }
>
> ----------------------------------
> Summarized: C Style, nullable and same problems as with
> solutions #3.
>
> ---- Solution #5 ----
>
> // Use classes
> class A { }
>
> // Works for lvalues and rvalues
> void foo(A a) {
>
> }
>
> ----------------------------------
> Summarized: flexible, efficient, no code bloat and same
> creation (with static opCall) as structs. But: heap allocations
> and nullable.
Honestly, I'd go with option 1. With a mixin template, it should
be pretty to not mess up too hard.
Also, In regards to multi-args, I'd just bite the bullet, and
make it so that if a single arg is rvalue, then all args are
rvalue. Not perfect, but I think it is a good cost to gain ratio.
Here is a mixin template that *almost* does it:
//----
import std.stdio;
import std.conv;
import std.traits;
template rvalue(alias fun, string funs)
{
private string ss()
{
//enum funs = fun.stringof; Don't know how to get
function name :(
enum Ret = ReturnType!fun.stringof;
alias Args = ParameterTypeTuple!fun;
alias ParameterStorageClassTuple!fun pstc;
enum names = [ParameterIdentifierTuple!fun];
string s;
s ~= Ret ~ " " ~ funs ~ "(";
foreach(i, Type; Args[0 .. $])
{
if (pstc[i] == ParameterStorageClass.scope_) s ~=
"scope ";
if (pstc[i] == ParameterStorageClass.out_) s ~=
"out ";
if (pstc[i] == ParameterStorageClass.lazy_) s ~=
"lazy ";
//if (pstc[i] == ParameterStorageClass.ref_) s ~=
"ref "; //Commented: That's the whole point ;)
s ~= Args[i].stringof ~ " ";
s ~= names[i];
if (i + 1 != Args.length) s ~= ", ";
}
s ~= ")";
//TODO: print the FunctionAttribute
s ~= "\n{\n return " ~ funs ~ "(";
if (Args.length)
{
s ~= names[0];
foreach(i, Type; Args[1 .. $])
{
s ~= ", " ~ names[i + 1];
}
}
s ~= ");\n}\n";
return s;
}
enum rvalue = ss();
}
void foo(ref int a, ref const int b, scope int c)
{
writefln("%s %s %s", a, b, c);
}
mixin(rvalue!(foo, "foo"));
void main()
{
foo(1, 2, 3);
writeln(rvalue!(foo, "foo"));
}
//----
1 2 3
void foo(int a, const(int) b, scope int c)
{
return foo(a, b, c);
}
//----
See? pretty nice. The only thing missing is actually getting the
function name :/ I'm not sure how to do it, so I passed two
arguments, but it should be doable with just 1 (worst case
scenario, you pass just the string).
Also, I didn't code the FunctionAttribute part, but that's just
because it's late and I want to sleep ;) It should be just about
the same as with ParameterStorageClass.
You *could* further improve on this design, if you so felt like
it, so that it generates all combination of ref/non ref
parameters. That's more complicated. But doable.
More information about the Digitalmars-d-learn
mailing list