-
Notifications
You must be signed in to change notification settings - Fork 3
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
assert in move assign operator #4
Comments
According to the C++ standard (i.e. in case of I unfortunately never realized this kind of "interaction" between moving-from and the empty state for more complex types. This can cause troubles in the general case. Imagine a type I will have to think about this problem. Since I am currently away, I won't be able to work on this for the next week. But if the move constructor/assignment operator of your type destroys any non-trivially-destructible members, or if it contains only trivially-destructible-members ( |
I had a closer look. Whenever the payload of the optional changes somehow "externally" without the optional's reset function or assignment with The idea with My best idea currently to fix the issues is to require that The debug assert in the move-assignment would then be wrong. @J-Richter Would this change of API cause problems for you? Do you use types where |
I use a class that is similar to the following Here the empty state (value_==0) cannot be constructed with the official interface of the #include "tinyoptional.h"
#include <bld/initialize.h>
#include <cstddef>
#include <cstring>
#include <cstdlib>
#include <utility>
class Int
{
int value_;
public:
Int( int val )
: value_( val )
{}
Int( Int const& rhs )
: value_( rhs.value_ )
{}
Int( Int && rhs )
: value_( rhs.value_ )
{
rhs.value_ = 0;
}
Int& operator=( Int val )
{
value_ = val.value_;
return *this;
}
int getValue() const
{
return value_;
}
};
class OddInt
{
Int value_;
public:
OddInt( Int value )
: value_( value )
{
assert( value_.getValue() & 1 );
}
};
template<> struct tiny::optional_flag_manipulator<OddInt>
{
static bool is_empty( OddInt const& n ) noexcept
{
return reinterpret_cast<Int const*>( &n )->getValue() == 0;
}
static void init_empty_flag( OddInt& n ) noexcept
{
::new( &n ) Int( 0 );
}
static void invalidate_empty_flag( OddInt& n ) noexcept
{
reinterpret_cast<Int*>( &n )->~Int();
}
};
int main( int, char** )
{
tiny::optional<OddInt> s1;
s1 = OddInt( Int( 45 ) );
tiny::optional<OddInt> s2;
s2 = std::move( s1 );
} I think it cannot happen that the object is changed externally, at least with move. Even moving the contained value like However, I am not quite sure. Maybe you can think of another counterexample. I think it would be bad if you lose the ability to construct only a part of the object. This is one of the strong points of this library. |
After thinking a bit more about the issue, I think that there may not be a problem here after all. In my example, the A similar problem exists in the original class in my source code. After I fixed it, the assert doesn't hit anymore either. |
…e readme regarding the problems when the transition to/from the empty state happens outside of tiny::optional. This was triggered by issue #4.
After thinking some more days about this problem, I failed to come up with a reasonable solution to support payload types in general where some of its member function causes a transition to the empty state (e.g. move assignment operator or constructor; except of course the function used by the tiny::optional<T> o = ...; // non empty o
o.value().MakeEmpty(); or also: tiny::optional<T> o = ...; // non empty o
T t = std::move(*o); // Calls move assignment operator of T assuming that So, I pushed a commit (4c9e940) and new release (v1.1.1):
|
The operator
MoveAssignmentBase & operator=(MoveAssignmentBase && rhs)
has this assert:It triggers in our code. The reason is that
might set rhs to the empty state if the moved-from-state happens to be the empty-state. I don't know what the assert is supposed to protect. It looks unnecessary. Could there be problems if I remove it?
The text was updated successfully, but these errors were encountered: