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

Add a copy function for span as mentioned in issue #248 #344

Merged
merged 1 commit into from
Nov 17, 2016

Conversation

MikeGitb
Copy link
Contributor

@MikeGitb MikeGitb commented Aug 29, 2016

Update: The original eiscription is completely outdated -- see the following posts.


Original:
This PR implements a copy function for span similar to what was mentioned in issue #248. However, instead of void, it returns a span representing the remaining space in the destination span.

There are probably a lot of style issues to be addressed and I'd be happy to incorporate any feedback, but my main question at the moment would be if the design is OK and if that function should be put into the span header as I did or into some separate utility / algorithms header.

@msftclas
Copy link

Hi @MikeGitb, I'm your friendly neighborhood Microsoft Pull Request Bot (You can call me MSBOT). Thanks for your contribution!

In order for us to evaluate and accept your PR, we ask that you sign a contribution license agreement. It's all electronic and will take just minutes. I promise there's no faxing. https://cla.microsoft.com.

TTYL, MSBOT;

@msftclas
Copy link

@MikeGitb, Thanks for signing the contribution license agreement so quickly! Actual humans will now validate the agreement and then evaluate the PR.

Thanks, MSBOT;

@MikeGitb
Copy link
Contributor Author

I put the function and tests into separate files for now to prevent re-basing conflicts in the future. I'd be happy to move the contents into existing files if that is preferred.

@MikeGitb MikeGitb force-pushed the add_copy branch 2 times, most recently from 62f15e3 to 05032e7 Compare September 21, 2016 21:37
@MikeGitb MikeGitb changed the title Add a copy function for span as mentioned in issu #248 Add a copy function for span as mentioned in issue #248 Sep 21, 2016
@neilmacintosh neilmacintosh self-assigned this Sep 22, 2016
@MikeGitb
Copy link
Contributor Author

Upon revisiting this PR I realized that returning the remaining destination space is maybe not the most intuitive semantics. It was born from from my primary use case to successively fill a buffer, but that might not be such a common use case in the wild.

Possible alternatives:

  • Return a span over the copied elements (the inverse from what it returns now).
  • Return the number of copied elements (which is always src.size()).
  • Don't return anything for now.

Any thoughts?

@MikeGitb
Copy link
Contributor Author

MikeGitb commented Sep 24, 2016

After seeing this version again in @BjarneStroustrup's keynote slides, I settled - at least for this PR - for the simple version that returns nothing.

The question if and what the function should return in addition can then be discussed separately.

Copy link
Collaborator

@neilmacintosh neilmacintosh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for putting this pack together @MikeGitb! Sorry to take so long to get to reviewing it!

I'm still not 100% sure we shouldn't match std::copy_n and return a span that contains the "remaining" area of the destination span. I'll go back and reread your thinking on that and try to form an opinion.

#pragma warning(pop)
#endif

#endif // GSL_SPAN_H
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I think this should be GSL_ALGORITHM_H


// turn off some misguided warnings
#pragma warning(push)
#pragma warning(disable : 4351) // warns about newly introduced aggregate initializer behavior
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure either of these would fire for this header, so you should be able to remove the whole push/pop sequence.

#define noexcept /*noexcept*/
#endif

#pragma push_macro("alignof")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I couldn't see alignof being used (maybe I missed it). But if it is not used, we can get rid of this push/pop sequence.


template<class SrcElementType, std::ptrdiff_t SrcExtent,
class DestElementType, std::ptrdiff_t DestExtent>
void copy(const span<SrcElementType, SrcExtent> src, span<DestElementType, DestExtent> dest)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The const on the first span is unnecessary and probably misleading if passing by-value (as you should rightly do here).

#ifdef GSL_THROW_ON_CONTRACT_VIOLATION

#ifdef _MSC_VER
#pragma push_macro("noexcept")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given there's no noexcept in this file, I think you can get rid of this push/pop sequence too.

// VS 2013 workarounds
#if _MSC_VER <= 1800

#define GSL_MSVC_HAS_VARIADIC_CTOR_BUG
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None of these define's should be necessary for this file I hope.

#pragma warning(disable : 26481 26482 26483 26485 26490 26491 26492 26493 26495)

// No MSVC does constexpr fully yet
#pragma push_macro("constexpr")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no use of constexpr here so this block and its corresponding "pop" can go.

}
}

TEST(copy_span_static_diff_type)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is for a type that is assignable. Could we have a test that validates that the reverse assignment (for example) does not compile? Similarly, we should probably validate that you can't accidentally slice objects using this function.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should slicing really be prevented? Although it is rarely necessary, I actually like the fact, that std::copy / std::copy_n allow copying from one type to another. If that should not be the case, then we probably should make input and output type identical (modulo constness and maybe volatile)

@neilmacintosh neilmacintosh added review and removed open labels Nov 5, 2016
@MikeGitb
Copy link
Contributor Author

MikeGitb commented Nov 5, 2016

Thanks for the feedback. The header and footer where dump copy past from another file and didn't clean it up afterwards. I'll remove the things you mentioned and expand the tests.

@MikeGitb
Copy link
Contributor Author

MikeGitb commented Nov 12, 2016

@neilmacintosh: I adressed some of your points, but not all:

  • Regarding the return type: Personally I'd also prefer to return the remaining target range, I just followed the specification presented by @BjarneStroustrup. The other thing is that the iterator returned by std::copy_n can be viewed both as the end of the copied elements or the start of remaining range. For gsl::copy, we have to make a decision for one ot the other.
    In any case, I think this can be discussed in a separete issue/PR. Adding a return value is not a big problem
  • The question about slicing and narrowing conversion: I'm following the convention by the stl, but we can make it more conservative e.g. by
    • requiring that source and destination span have the same element types
    • Allowing different types, but but not allowing narrowing conversions

@neilmacintosh
Copy link
Collaborator

@MikeGitb I think you are correct to follow the std::copy_n convention here regarding the slicing and narrowing conversions. It's not perfect, but it will be unsurprising to follow existing standard library practice there.

I had a think about the return value, and although Bjarnes slides demonstrate a void return type, I think that - again - it would be good to stick with the conventions set by the standard library (except in cases where we think they are bad practice). In this case, it seems relatively easy to return aspanwhich runs from one past the last-written element indesttodest.end(). If there are no unwritten elements remaining indest`, then you would just return an empty span. I think this also supports use cases like your original one - where you want to progressively fill a buffer.

However, I can understand if you'd like to take a second PR to add the return type. This has been sitting around for a while ;-)

Let me know your preference...

@MikeGitb
Copy link
Contributor Author

@neilmacintosh: As the decision about the return type is made it doesn't really matter for me, but if you are fine with the rest, I'd prefer if you merge the PR as it is. Adding the return type is simple, but in case the code and/or unittest changes introduce any issues, I'd like to discuss/fix them separately, as I only work on this very irregularly.

@neilmacintosh
Copy link
Collaborator

Makes sense @MikeGitb. I'm happy with everything in this PR, and agree we can always change the return type separately. Thanks for taking on this work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants