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

Use strongly typed configuration options instead of multiple bools #45

Open
jk-jeon opened this issue Mar 29, 2021 · 4 comments
Open

Use strongly typed configuration options instead of multiple bools #45

jk-jeon opened this issue Mar 29, 2021 · 4 comments

Comments

@jk-jeon
Copy link

jk-jeon commented Mar 29, 2021

@Naios Here are some suggestions about fu2::function_base.

  1. There are too many boolean template parameters. It's hard to imagine what specific combination of policies are given if we just write
template<typename Arg>
using my_consumer = fu2::function_base<true, false, fu2::capacity_fixed<100U>,
                                       true, false, void(Arg)&&>;

In my opinion, better alternatives might be:

  • Use separate enum types for each policy parameter, or
  • Change policy parameters from non-type parameters to type parameters, and define new empty type for each policy.

The second approach might require more template metaprogramming, but it's open-ended (users can add more options at their will) while the enum approach is closed-ended. This might be either pros or cons, though.

I recommend the enum approach, and I think there is virtually no downside of it compared to the boolean approach, except that the implementation might be a bit more verbose.

  1. This one is about README. I'm not sure what HasStrongExceptGuarantee is meant to mean. I mean, I know what strong exception guarantee means in general, but I think it might be better to explicitly say (1) where are the places fu2::function_base is guarding against exceptions when HasStrongExceptGuarantee is set to be true, and (2) exactly what invariants are preserved. I assumed these are about copy assignment, is that correct?

Thanks!

@Naios
Copy link
Owner

Naios commented Mar 29, 2021

Yes, you are right about the bool configuration. Using a strongly typed enum would prevent misconfiguration and would be an improvement. However, changing this leads to a breaking change that I could do earliest at the next major version bump.

Currently, the HasStrongExceptGuarantee only propagates noexcept from erased objects to the signature of the move construct and move assign of the type erasure such that containers can optimize their behavior based on that.
There are no guarantees made (yet) about the strong exception guarantees of the type erasure (function_base) itself.

@jk-jeon
Copy link
Author

jk-jeon commented Mar 30, 2021

Yes, you are right about the bool configuration. Using a strongly typed enum would prevent misconfiguration and would be an improvement. However, changing this leads to a breaking change that I could do earliest at the next major version bump.

Sounds great.

Currently, the HasStrongExceptGuarantee only propagates noexcept from erased objects to the signature of the move construct and move assign of the type erasure such that containers can optimize their behavior based on that.
There are no guarantees made (yet) about the strong exception guarantees of the type erasure (function_base) itself.

Hmm. I'm not sure if I got you correctly. So my current understanding is that, if the underlying object's move constructor/assignment are not noexcept, and if HasStrongExceptGuarantee is set to be true, and if SBO is in action, then the move actually behaves as if it were copy. Is this correct?

@jk-jeon jk-jeon changed the title [feature request] Suggestions about fu2::function_base Suggestions about fu2::function_base Mar 30, 2021
@Naios
Copy link
Owner

Naios commented Mar 30, 2021

https://en.cppreference.com/w/cpp/language/exceptions

  1. Nothrow (or nofail) exception guarantee -- the function never throws exceptions. Nothrow (errors are reported by other means or concealed) is expected of destructors and other functions that may be called during stack unwinding. The destructors are noexcept by default. (since C++11) Nofail (the function always succeeds) is expected of swaps, move constructors, and other functions used by those that provide strong exception guarantee.
  1. Strong exception guarantee -- If the function throws an exception, the state of the program is rolled back to the state just before the function call. (for example, std::vector::push_back)

Currently point 2) is not supported by function2. The only thing that HasStrongExceptGuarantee does is to mark its move constructor, move assignment operator, and destructor as noexcept and requires the wrapped object to also have a noexcept move constructor, move assignment operator, and destructor. The reason for this is that std::vector and other containers of the standard library would default to a copy instead of a cheap move operation otherwise.

By marking the move constructor, move assignment operator, and destructor of the function2 type-erasure as noexcept we implicitly provide the strong exception guarantee through being 1) Nothrow.

I see that this case is misleading and it would be better if we rename HasStrongExceptGuarantee to HasNoexcept while changing the behavior of the original HasStrongExceptGuarantee to conforming to 2) without requiring the wrapped object to have a noexcept move constructor, move assignment operator and destructor.

@jk-jeon
Copy link
Author

jk-jeon commented Mar 30, 2021

Thanks for clarification. Looking forward to the next release!

@Naios Naios changed the title Suggestions about fu2::function_base Use strongly typed configuration options instead of multiple bools Mar 30, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants