I would only choose the std::optional
approach if the class had a single member. So in this case, having a bool
member for indicating the validity of an instance of the class seems fine.
Using the bool
member you can implement an overloaded operator bool()
for the class. This way, expressions like if (session_instance)
are possible (instead of writing if (session_instance.id != -1)
or if (session_instance.id.has_value())
, etc).
An example:
#include <utility>
#include <cstdint>
#include <cstddef>
#include <cstdio>
class Session {
public:
explicit Session(const std::uint32_t id, const std::size_t size = 10)
: is_valid { true }, m_id { id }, m_buffer { new char[size] }
{
m_buffer[size - 1] = '\0';
}
~Session()
{
if ( m_buffer != nullptr )
delete[] m_buffer;
}
Session(const Session&) = delete;
Session& operator = (const Session&) = delete;
Session(Session&& rhs) noexcept
: is_valid { std::exchange(rhs.is_valid, false) },
m_id { std::exchange(rhs.m_id, 0) },
m_buffer { std::exchange(rhs.m_buffer, nullptr) }
{}
Session& operator = (Session&& rhs) noexcept
{
if ( this != &rhs )
{
is_valid = std::exchange(rhs.is_valid, false);
m_id = std::exchange(rhs.m_id, 0);
if ( m_buffer != nullptr )
delete[] m_buffer;
m_buffer = std::exchange(rhs.m_buffer, nullptr);
}
return *this;
}
operator bool () const noexcept
{
return is_valid;
}
private:
bool is_valid;
std::uint32_t m_id;
char* m_buffer { nullptr };
};
int main( )
{
Session ses { 1000, 10 };
Session ses2 { 100, 20 };
ses2 = std::move( ses );
if ( ses )
std::printf( "ses is valid\n");
else
std::printf( "ses is NOT valid\n");
}
Note: The operator bool()
can also be implemented with return m_id != -1;
in case of changing the type of m_id
to int
. Then no extra bool
member will be required. You can simply add a member variable to your class like inline static constexpr int invalid_id { -1 };
and compare m_id
with it inside the operator bool()
.