Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

question about copy elision #3414

Closed
schroffl opened this issue Oct 9, 2019 · 5 comments
Closed

question about copy elision #3414

schroffl opened this issue Oct 9, 2019 · 5 comments
Labels
question No questions on the issue tracker, please.
Milestone

Comments

@schroffl
Copy link
Contributor

schroffl commented Oct 9, 2019

Hey guys,

I have a question about the newly introduced copy elision. Is the compiler able to determine that it should immediately write into first_set.data in the unionize function?

const std = @import("std");

fn getByte(n: usize) usize {
    return n >> 3;
}

fn getBitOffset(n: usize) u3 {
    return @intCast(u3, n & 7);
}

fn setBit(bytes: var, bit: usize) void {
    const offset = getByte(bit);
    const idx = getBitOffset(bit);

    bytes[offset] |= (u8(1) << idx);
}

pub fn Set(comptime capacity: usize) type {
    const data_size = capacity / 8;

    return struct {
        const Self = @This();

        data: [data_size]u8,

        pub fn init() Self {
            return Self{ .data = [_]u8{0} ** data_size };
        }

        pub fn add(self: *Self, bit: usize) void {
            setBit(&self.data, bit);
        }

        pub fn unionize(a: Self, b: Self) Self {
            var result: Self = Self.init();
            var i: usize = 0;

            while (i < data_size) : (i += 1) {
                // Is this effectively equal to `a` being of type `*Self` and doing
                //     a.data[i] |= b.data[i];

                result.data[i] = a.data[i] | b.data[i];
            }

            return result;
        }
    };
}

pub fn main() anyerror!void {
    const MySet = Set(100);

    var first_set = MySet.init();
    var second_set = MySet.init();

    second_set.add(10);

    first_set = first_set.unionize(second_set);
}

Edit: I'm sorry if this seems like a code-dump, but I wanted to provide a running example :)

@andrewrk andrewrk added the question No questions on the issue tracker, please. label Oct 9, 2019
@andrewrk andrewrk added this to the 0.6.0 milestone Oct 9, 2019
@andrewrk
Copy link
Member

andrewrk commented Oct 9, 2019

This is #2765.

@andrewrk andrewrk closed this as completed Oct 9, 2019
@schroffl
Copy link
Contributor Author

schroffl commented Oct 9, 2019

Awesome, thank you very much :)

Related question: Do you advise against designing an API around this feature? Would it be more reliable to have my function still take a pointer to *Self, because the elision can be fooled in some cases?

@schroffl
Copy link
Contributor Author

schroffl commented Oct 9, 2019

Bump – You upvoted my comment just before I made the edit, which makes me think you're never going to see it otherwise. I'm sorry if that's not the case ^^

@andrewrk
Copy link
Member

andrewrk commented Oct 9, 2019

If the semantics of your application depend on elision, you can't write the code this way, you'll have to take a pointer. But I fully intend on making #2765 a reality, which means that when the issue is implemented, you could then improve your API to not need to take a pointer anymore. There are a bunch of places in the std lib that are affected in this way.

@schroffl
Copy link
Contributor Author

schroffl commented Oct 9, 2019

Oh... didn't notice the issue is still open. I'll wait it out then.

Thanks for your (and every other contributors) work by the way. I never really used Zig for something productive, but it got me into low-level programming and is amazingly fun to work with :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question No questions on the issue tracker, please.
Projects
None yet
Development

No branches or pull requests

2 participants