tl::optional now based on internal implementation, added tests and tl::to_string binding

This commit is contained in:
Matthias Koefferlein 2024-03-09 15:48:45 +01:00
parent eea4344976
commit d811474d8f
4 changed files with 177 additions and 85 deletions

View File

@ -25,8 +25,6 @@
namespace tl
{
#if __cplusplus < 201703L
extern const nullopt_t nullopt = nullopt_t();
#endif
extern const nullopt_t nullopt = nullopt_t ();
} // namespace tl

View File

@ -24,136 +24,132 @@
#define HDR_tlOptional
#include "tlAssert.h"
#include "tlString.h"
#include "tlCommon.h"
#include <iostream>
#include <optional>
namespace tl
{
#if __cplusplus >= 201703L
template<typename T>
class optional : public std::optional<T> {};
#else
struct nullopt_t {};
extern const nullopt_t nullopt;
/*
* Poor man's partly implementation of C++17's std::optional
/**
* @brief Poor man's partial implementation of C++17's std::optional
*/
template<typename T>
class optional
class TL_PUBLIC_TEMPLATE optional
{
public:
optional() :
a_value(),
a_isValid(false)
{}
optional () :
m_value (),
m_is_valid (false)
{}
optional(const nullopt_t&) :
a_value(),
a_isValid(false)
{}
optional (const nullopt_t &) :
m_value (),
m_is_valid (false)
{}
optional(const T &value) :
a_value(value),
a_isValid(true)
{}
optional (const T &value) :
m_value (value),
m_is_valid (true)
{}
void reset()
{
a_isValid = false;
}
void reset ()
{
m_is_valid = false;
}
bool has_value() const { return a_isValid; }
bool has_value() const { return m_is_valid; }
T &value()
{
tl_assert(a_isValid);
T &value ()
{
tl_assert (m_is_valid);
return a_value;
}
return m_value;
}
const T &value() const
{
tl_assert(a_isValid);
const T &value () const
{
tl_assert (m_is_valid);
return a_value;
}
return m_value;
}
T& operator* ()
{
return value();
}
T& operator* ()
{
return value ();
}
const T& operator* () const
{
return value();
}
const T& operator* () const
{
return value ();
}
T* operator-> ()
{
return &value();
}
T* operator-> ()
{
return m_is_valid ? &m_value : 0;
}
const T* operator-> () const
{
return &value();
}
const T* operator-> () const
{
return m_is_valid ? &m_value : 0;
}
private:
T a_value;
bool a_isValid;
T m_value;
bool m_is_valid;
};
template<typename T>
optional<T> make_optional(const T& value)
optional<T> make_optional (const T &value)
{
return optional<T>(value);
return optional<T> (value);
}
template<typename T>
bool operator==(const optional<T> &lhs, const optional<T> &rhs)
bool operator== (const optional<T> &lhs, const optional<T> &rhs)
{
if (lhs.has_value() != rhs.has_value())
{
return false;
}
if (lhs.has_value () != rhs.has_value ()) {
return false;
}
if (!lhs.has_value ()) {
return true;
}
if (!lhs.has_value())
{
return true;
}
return lhs.value() == rhs.value();
return lhs.value() == rhs.value();
}
template<typename T>
bool operator!=(const optional<T> &lhs, const optional<T> &rhs)
bool operator!= (const optional<T> &lhs, const optional<T> &rhs)
{
return !(lhs == rhs);
return !(lhs == rhs);
}
template<typename T>
std::ostream &operator<<(std::ostream &ostr, const optional<T> &rhs)
std::ostream &operator<< (std::ostream &ostr, const optional<T> &rhs)
{
if (rhs.has_value())
{
ostr << rhs.value();
}
else
{
ostr << "<invalid>";
}
if (rhs.has_value()) {
ostr << rhs.value();
} else {
ostr << "<invalid>";
}
return ostr;
return ostr;
}
#endif /* __cplusplus >= 201703L */
template <class T>
std::string to_string (const optional<T> &opt)
{
if (opt.has_value ()) {
return tl::to_string (*opt);
} else {
return std::string ();
}
}
} // namespace tl

View File

@ -0,0 +1,97 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2024 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "tlOptional.h"
#include "tlUnitTest.h"
namespace
{
TEST(1_Basic)
{
tl::optional<int> opt;
// value not set
EXPECT_EQ (opt.has_value (), false);
EXPECT_EQ (opt.operator-> (), (int *) 0);
EXPECT_EQ (((const tl::optional<int> &) opt).operator-> (), (const int *) 0);
EXPECT_EQ (tl::to_string (opt), "");
try {
opt.value (); // asserts
EXPECT_EQ (true, false);
} catch (...) {
}
// make_optional, assignment
opt = tl::make_optional (17);
// value set
EXPECT_EQ (opt.has_value (), true);
EXPECT_EQ (opt.value (), 17);
EXPECT_EQ (tl::to_string (opt), "17");
EXPECT_EQ (((const tl::optional<int> &) opt).value (), 17);
EXPECT_EQ (*opt, 17);
EXPECT_EQ (*((const tl::optional<int> &) opt), 17);
EXPECT_EQ (*(opt.operator-> ()), 17);
EXPECT_EQ (*(((const tl::optional<int> &) opt).operator-> ()), 17);
// compare operators
EXPECT_EQ (opt == tl::make_optional (-1), false);
EXPECT_EQ (opt == tl::make_optional (17), true);
EXPECT_EQ (opt == tl::optional<int> (), false);
EXPECT_EQ (opt != tl::make_optional (-1), true);
EXPECT_EQ (opt != tl::make_optional (17), false);
EXPECT_EQ (opt != tl::optional<int> (), true);
// copy ctor
tl::optional<int> opt2 (opt);
EXPECT_EQ (opt2.has_value (), true);
EXPECT_EQ (opt2.value (), 17);
// reset method
opt = tl::make_optional (17);
opt.reset ();
EXPECT_EQ (opt.has_value (), false);
EXPECT_EQ (opt == tl::optional<int> (), true);
EXPECT_EQ (opt != tl::optional<int> (), false);
// tl::nullopt tag
opt = tl::make_optional (17);
opt = tl::optional<int> (tl::nullopt);
EXPECT_EQ (opt.has_value (), false);
EXPECT_EQ (opt == tl::optional<int> (), true);
EXPECT_EQ (opt != tl::optional<int> (), false);
}
}

View File

@ -31,6 +31,7 @@ SOURCES = \
tlLongIntTests.cc \
tlMathTests.cc \
tlObjectTests.cc \
tlOptionalTests.cc \
tlPixelBufferTests.cc \
tlResourcesTests.cc \
tlReuseVectorTests.cc \