-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Use std::array in base_uint instead of C-style array #2514
Conversation
This looks good to me. 👍. Thanks @JoeLoser! |
Jenkins Build SummaryBuilt from this commit Built at 20180531 - 16:35:04 Test Results
|
Codecov Report
@@ Coverage Diff @@
## develop #2514 +/- ##
===========================================
- Coverage 70.66% 70.64% -0.02%
===========================================
Files 696 696
Lines 54405 54405
===========================================
- Hits 38444 38437 -7
- Misses 15961 15968 +7
Continue to review full report at Codecov.
|
src/ripple/basics/base_uint.h
Outdated
@@ -419,7 +419,7 @@ class base_uint | |||
|
|||
base_uint<Bits, Tag>& operator=(Zero) | |||
{ | |||
memset (&pn[0], 0, sizeof (pn)); | |||
memset (pn.data (), 0, sizeof (pn)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can now be:
pn.fill(0);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similarly, does the need for compare
(at line 435) go away, and we can implement comparisons by delegating to the comparison operators for std::array
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nbougalis Sorry for the long latency response w/ CppNow going on. As far I can tell,
- We can remove
compare
inbase_uint.h
and delegate like you suggested just by making the comparison ops friends. - For fixing the call sites that were relying on this
compare
function being available to define their own ordering (such asIssue.cpp
), we can then just use the comparison operators directly.
This weekend, I should have some free time to clean up this PR and I'll post a proposed patch then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After digging into this for a little bit, I'd prefer to punt on this for now. Implementing the comparison operators just as delegating to the std::array
comparison ops didn't "just work". Plus, it looks like we pass this compare
function around as a function object in a different place (TxMeta.cpp
).
So, my preference would be that I'll create a GitHub issue to capture this idea but do not wish to couple it with this PR, even though it may naturally seem like a good candidate.
Edit: created an issue
The copy assignment operator can now be |
@HowardHinnant thanks for the feedback. I'll make those good changes tonight and send a patch up for @seelabs to pull in to this. There may be other places to leverage simple standard algorithms too, so I'll look into that. |
There's a |
@@ -314,7 +314,7 @@ class base_uint | |||
Hasher& h, base_uint const& a) noexcept | |||
{ | |||
// Do not allow any endian transformations on this memory | |||
h(a.pn, sizeof(a.pn)); | |||
h(a.pn.data (), sizeof(a.pn)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given:
std::array<T, N> a;
T b[N];
are we guaranteed that sizeof(a) == sizeof(b)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe so. According to CppRef, "This container is an aggregate type with the same semantics as a struct holding a C-style array T[N] as its only non-static data member. "
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I'm pretty sure that's the case. In the C++17 standard Section 26.3.7.1, Class template array overview paragraph 1 says in part:
An instance of array<T, N> stores N elements of type T, so that size() == N is an invariant.
Then paragraph 2 says:
An array is an aggregate (11.6.1) that can be list-initialized with up to N elements whose
types are convertible to T.
Between those two guarantees I think we're good.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, especially when N == 0
. That being said, the following program compiles on all of our target platforms:
#include <array>
#include <cstdint>
template <class T, std::size_t N>
void
test()
{
std::array<T, N> a;
T b[N];
static_assert(sizeof(a) == sizeof(b), "");
}
int
main()
{
test<char, 1>();
test<char, 2>();
test<char, 3>();
test<short, 1>();
test<short, 2>();
test<short, 3>();
test<int, 1>();
test<int, 2>();
test<int, 3>();
test<long long, 1>();
test<long long, 2>();
test<long long, 3>();
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that in practice on all major vendors, this holds for all N
other than N == 0
like @HowardHinnant alluded to. See this StackOverflow post for some more standardese-explanation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yipes! I missed zero. Good point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I went down this path thinking about the "degenerate" case where N == 0
and then wondered if there are other cases where this could happen.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do people have a preference of how to defend against this? I am leaning towards just adding a static_assert(WIDTH != 0, "Cannot have 0-sized base_uint");
to avoid these sort of surprises.
Great observation about the N == 0
case @nbougalis.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@JoeLoser base_uint
already has
static_assert (Bits >= 64,
"The length of a base_uint in bits must be at least 64.");
Also, @HowardHinnant suggestion of static_assert(sizeof(pn) == bytes, "")
will also protect against this. I don't think we need a WIDTH != 0
check
@@ -143,7 +143,7 @@ class base_uint | |||
assert (vch.size () == size ()); | |||
|
|||
if (vch.size () == size ()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we already assert this condition right above, I'm just going to collapse this conditional in my patch later today.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wouldn't remove the condition. Although it would be a logic error is the sizes don't match, it's also a change in behavior that would fall outside the scope of this PR. We do sometimes do small unrelated cleanups in PRs, but base_uint is a pretty fundamental type and changes in behavior need to be carefully considered.
So good idea, but my vote is "not for this PR".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very valid points. I'll save it for a different PR. Unnecessary coupling isn't good, especially given how new I am to the codebase.
@seelabs I believe I've addressed all the great feedback. I opted to punt on Nik's comment and created a GH issue to track that idea. I didn't know how you would feel about me pushing directly to |
Pushed latest changes from @JoeLoser |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me. Needs rebase though.
Rebased and squashed |
This should have been marked as passed and put into 1.1.0-b2. Apologies @JoeLoser, we'll get it into the next beta. |
@seelabs no worries. Next beta is in a week or so I imagine, so no big deal. |
in 0b2f33d |
This is the new PR for #2509