Maik Klein
Maik Klein

Reputation: 16148

Forwarding variadic arguments containing non copyable types

void print1(Args...)(Args args){
    print2(args);
}
void print2(Args...)(Args args){
    //do something
}

And you can call it like this

print1(1, 2);

But what if there is a non copyable type inside the variadic argument?

struct Foo{
    @disable this(this);
    ~this(){
    }
}

then

print(1, 2, Foo());

Error: struct app.Foo is not copyable because it is annotated with @disable

It should be possible with mixins

void print1(Args...)(Args args){
    mixin(forward!(print2, Args));
}

which would expand to

// with `print(1, 2, Foo());`
void print1(Args...)(Args args){
    mixin("print2(args[0], args[1], args[2].move()");
}

Are there any other alternatives besides this? Does something like this already exist?

Upvotes: 1

Views: 67

Answers (1)

Colonel Thirty Two
Colonel Thirty Two

Reputation: 26579

Your print1 and print2 functions are accepting function parameters by-value, meaning they are copied when passed in. This, of course, does not work with non-copyable values (unless you move them in, which invalidates the source value).

To accept non-copyable values, you need to pass them by-reference. The easiest way to do that with variadic templates is by using auto ref:

void print1(Args...)(auto ref Args args) { ... }

With auto ref, any arguments that can be passed by-reference will be.

You can also combine this with std.functional.forward:

void print2(Args...)(auto ref Args args) { ... }
void print1(Args...)(Args args) {
    print2(forward!args);
}

Upvotes: 3

Related Questions