Uh oh!
There was an error while loading. Please reload this page.
Convenience constructor templates for buffer_info - #860
Conversation
0fe6005 to
b693b01Comparedean0x7d
commented
May 17, 2017
That's a nice reduction of arguments. Looks good to me. |
YannickJadoul
commented
May 17, 2017
Somehow the builds are failing on gcc 4.8, though. gcc 6 and clang do work. And on my own system (gcc 5.4), I had to use brace-initialization. For some reason, it seems that the compiler first moves the arguments to the other constructor, and only then gets the |
…ize, format string, and number of dimensions from the pointer type and the shape container
b693b01 to
09b1f95Comparedean0x7d
commented
May 17, 2017
I think the frequent false positives on AppVeyor have desensitized me to seeing red in CI status. Totally missed the gcc 4.8 error. |
It's an argument evaluation order issue. |
YannickJadoul
commented
May 17, 2017
I'd agree, but there's two things why I'm not completely convinced:
|
Ah, but, stack overflow knows about a gcc bug: https://stackoverflow.com/questions/14060264/order-of-evaluation-of-elements-in-list-initialization Edit: another interesting StackOverflow thread: https://stackoverflow.com/questions/24814696/move-semantics-and-function-order-evaluation |
dean0x7d
commented
May 18, 2017
Regarding point 1, each argument is fully evaluated before moving on to the next one, so the rvalue-reference cast and move-constructor call happen back-to-back. MSVC has the same bug as gcc 4.8 regarding brace evaluation order. AFAIK this only affects calling constructors with braces, but not Unless someone has a better solution, I think making a copy of |
I ran into exactly the same issue in |
Let's see... *fingers crossed* Edit: woohoo, GCC 4.8 already seems to have succeeded. Should I also implement this solution for |
| } | ||
| private: | ||
| struct private_ctr_tag { explicit private_ctr_tag() = default; }; |
There was a problem hiding this comment.
Is there any pointer in declaring the default constructor here? (I.e. instead of just struct private_ctr_tag {};?)
There was a problem hiding this comment.
I think I saw that somewhere, and reckoned explicit would be appropriate for the constructor. But there's actually no point, since it's all private, anyway.
jagerman
commented
May 19, 2017
Actually, I don't think it's needed anymore; I forget exactly where it happened, but it looks like the current |
YannickJadoul
commented
May 19, 2017
Is there a reason for these two interfaces ( |
YannickJadoul
commented
May 19, 2017
Oh, also, on the topic of std::fill(strides.begin(), strides.end(), itemsize);
for (size_t i = 0; i < ndim - 1; i++)
for (size_t j = 0; j < ndim - 1 - i; j++)
strides[j] *= shape[ndim - 1 - i];could be simplified to the more efficient strides[ndim - 1] = itemsize;
for (size_t i = 1; i < ndim; ++i)
strides[ndim - 1 - i] = strides[ndim - i] * shape[ndim - i];If we leave |
jagerman
commented
May 20, 2017
Already pending in #762. |
…uctor taking rvalue reference, solving the evaluation order move problem
8cd91b1 to
2f2b803Comparejagerman
commented
May 20, 2017
I need the same trick in #762, so how about moving the |
jagerman
commented
May 20, 2017
Actually, never mind that. I'll move it as part of #762; you can leave this PR as-is. |
| for (size_t i = 0; i < (size_t) ndim; ++i) | ||
| size *= shape[i]; | ||
| } | ||
There was a problem hiding this comment.
Perhaps this could be redesigned a bit to only use this private constructor when you need the delegation, i.e. just in the one constructor at line 34 that wants to both move and call ->size. It makes the code a little easier to follow (one fewer delegation for most constructors), and invokes fewer moves. It's also essentially a workaround for MSVC and old gcc, rather than a particularly desirable design.
There was a problem hiding this comment.
This is what you mean?
This costs one extra move when you use the buffer_info(T *ptr, detail::any_container<ssize_t> shape_in, detail::any_container<ssize_t> strides_in) overload (as the private constuctor forwards it to the original overload and that one takes the containers by value before moving it into the data members, while before, the private constructor moved it immediately into the private members).
Then again, even if the optimizer doesn't figure that out, that extra move won't be thát costly, of course.
There was a problem hiding this comment.
Oh, right, it's not actually fewer delegations. Still, I like the idea of keeping the workaround as out-of-the-way as possible rather than pushing everything through it.
dean0x7d
commented
May 29, 2017
Merged, thanks @YannickJadoul! |
In order to reduce the amount of error-prone constructor arguments,
buffer_infowould now have a constructor template similar toarrayto automatically get the item size, default format string and number of dimensions.