-
Notifications
You must be signed in to change notification settings - Fork 61
Add emplace_{front,back} methods #15
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
base: develop
Are you sure you want to change the base?
Conversation
Is there no maintainer for circular_buffer anymore who can accept this patch? |
There is no active maintainer, but I'm happy to review this (and eventually merge it when it is suitable). |
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.
Summary of the requested changes:
- Only define these new function templates when
BOOST_NO_CXX11_VARIADIC_TEMPLATES
is not defined - Use
cb_details::allocator_traits
from this library, instead ofboost::container::allocator_traits
from Boost.Container - Add unit tests for the new functions
d8d423c
to
3217dc6
Compare
I believe I've addressed all of your feedback, and rebased onto current develop. Apparently there were some internal interface changes in boost in the meantime. |
I am having problems with emplacing when the buffer is full. Trying to emplace a new element when the buffer is full will trigger
(https://github.com/boostorg/circular_buffer/pull/15/files#diff-bc2e61cf0e1d5c347de205ddde4a5522R1459) An easy example (out of my mind, not tested): class Test
{
public:
Test(int, int) { std::cout << "C " << this << std::nl; }
Test(const Test&) = delete;
~Test() { std::cout << "D " << this << std::nl; }
};
boost::circular_buffer<Test> buffer(2);
buffer.emplace_back(1, 2);
buffer.emplace_back(2, 3);
buffer.emplace_back(3, 4); I don't know if this is expected behaviour, but in my case it conflicts with some pointers I am moving around. My quick patch (admittedly not consistent with the rest of the code) is diff --git a/include/boost/circular_buffer/base.hpp b/include/boost/circular_buffer/base.hpp
index 3502931..9d34c2e 100644
--- a/include/boost/circular_buffer/base.hpp
+++ b/include/boost/circular_buffer/base.hpp
@@ -1456,7 +1456,8 @@ private:
if (full()) {
if (empty())
return;
- replace(m_last, value_type(::boost::forward<Args>(args)...));
+ cb_details::allocator_traits<Alloc>::destroy(alloc(), boost::to_address(m_last));
+ cb_details::allocator_traits<Alloc>::construct(alloc(), boost::to_address(m_last), ::boost::forward<Args>(args)...);
increment(m_last);
m_first = m_last;
} else { AFAIK PR merged on
|
@AI0867, could you please continue this work? |
I hadn't realised someone had replied to this. I've rebased the branch locally, but I don't seem to have a working build environment for boost at the moment, so this may take some time. |
Looking forward to this... |
I've updated the code in line with its surroundings, and fixed the issue where a full buffer creates an intermediate value. Are there any other changes required? |
I have tried to figure out what the bug was and if there has been any fix related to this... My conclusion to this is: it is working as designed. In the documentation, it says that if the buffer is full, the last/first element will be destroyed before being replaced. Keep in mind that the placement new is used. Therefore, the this pointer value will remain the same between the old element being destroyed and the replacing element being constructed. I'm not too sure what replacing the replace function call by its body at the calling site can change anything. A more meaningful test would be to store the constructor parameters and print them in the constructor/destructor to discriminate the old and the new object. Using the this pointer for that purpose is inappropriate because of the placement new IOW: this pointer value when destructor is called will be equal to pos and the this pointer value when the constructor is called will ALSO be equal to pos even if they are 2 distinct objects, they share the same this value because they are located at the same address... Am I missing something?
|
@lano1106 I don't know if my comments are stil relevant anymore, it's been a few years since I have used As far as I remember, the implementation presented here created temporal values during At the time I didn't have time to work on a proper fix, certainly my proposed changes should never be commited as they were, and were meant just as a PoC and quick hack for myself. |
@gpascualg sure. This report is getting old... What I am saying is that because it is a sequence destructor-constructor, I guess that this can become confusing about which function is called before the other. I have run your test program with the original circular_buffer patch with the perfectly forwarding replace() function:
I am not seeing any temporal getting created and destructed... Here is a small modification of your test to implement my suggestion
the output:
see no problem with the original patch. imho, the original patch is superior because it respected the original design and style of the class... |
correct... but I think it is less good because:
I would go a step even further... The patch may have added unnecessary code duplication with the functions with compilers supporting variadic templates, I have the feeling that it could be possible to remove but this is just an idea and I would not want the PR to be stopped by this simple improvement idea that may/may not work... |
there is one thing that I wonder about... How do compilers choose the correct overload replace() when only 1 parameter is passed to the emplace functions? That might be what the whole bug was about... I am not a C++ lawyer knowing all the rules about overloading in the presence of variadic template candidates... maybe just renaming the variadic version of replace to something distinct would fix the bug and retain the benefits of the initial proposal... |
That output is exactly the behaviour I wanted and expected out of this PR. As it is, I concur that this diff is better and avoids duplication. |
no worry. I have been able to reproduce the issue... I think that the initial PR prior to rework to address the code review was working fine. This is the version that I was using when I did run your test. The code review rework did introduce the bug with the value_type construct when calling the replace function. I have been able to reproduce it when I started off writing my patch over the last PR version. |
No description provided.