FData improvements
This commit is contained in:
parent
b15a665729
commit
4478948bc7
|
@ -1,3 +1,6 @@
|
|||
2020-09-26 Markus Gans <guru.mail@muenster.de>
|
||||
* FData improvements
|
||||
|
||||
2020-09-25 Markus Gans <guru.mail@muenster.de>
|
||||
* std::clog now streams everything to the FLogger object
|
||||
* Added a unit test for the FData class
|
||||
|
|
|
@ -47,154 +47,9 @@
|
|||
namespace finalcut
|
||||
{
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// class FDataAccess
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
template <typename T>
|
||||
class FData; // Class forward declaration
|
||||
|
||||
class FDataAccess
|
||||
{
|
||||
public:
|
||||
// Constructor
|
||||
FDataAccess();
|
||||
|
||||
// Destructor
|
||||
virtual ~FDataAccess();
|
||||
|
||||
// Accessors
|
||||
virtual const FString getClassName() const
|
||||
{
|
||||
return "FDataAccess";
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const T& get() const
|
||||
{
|
||||
return static_cast<const FData<T>&>(*this).get();
|
||||
}
|
||||
|
||||
// Mutator
|
||||
template <typename T
|
||||
, typename V>
|
||||
void set (const V& v)
|
||||
{
|
||||
static_cast<FData<T>&>(*this).set(v);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// class FData
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
template <typename T>
|
||||
class FData : public FDataAccess
|
||||
{
|
||||
public:
|
||||
// Constructors
|
||||
explicit FData (T& v) // constructor
|
||||
: value_ref{v}
|
||||
{ }
|
||||
|
||||
explicit FData (T&& v) // constructor
|
||||
: value{std::move(v)}
|
||||
, value_ref{value}
|
||||
{ }
|
||||
|
||||
// Destructor
|
||||
~FData() override
|
||||
{ }
|
||||
|
||||
FData (const FData& d) // Copy constructor
|
||||
: value{d.value}
|
||||
, value_ref{value}
|
||||
{ }
|
||||
|
||||
FData (FData&& d) noexcept // Move constructor
|
||||
: value{std::move(d.value)}
|
||||
, value_ref{value}
|
||||
{ }
|
||||
|
||||
// Overloaded operators
|
||||
FData& operator = (const FData& d) // Copy assignment operator (=)
|
||||
{
|
||||
value = d.value;
|
||||
value_ref = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
FData& operator = (FData&& d) noexcept // Move assignment operator (=)
|
||||
{
|
||||
value = std::move(d.value);
|
||||
value_ref = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
T operator () () const
|
||||
{
|
||||
return value_ref;
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
T operator () (Args... args) const
|
||||
{
|
||||
return value_ref(args...);
|
||||
}
|
||||
|
||||
explicit operator T () const
|
||||
{
|
||||
return value_ref;
|
||||
}
|
||||
|
||||
FData& operator << (const T& v)
|
||||
{
|
||||
value_ref = v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Accessors
|
||||
const FString getClassName() const override
|
||||
{
|
||||
return "FData";
|
||||
}
|
||||
|
||||
T& get()
|
||||
{
|
||||
return value_ref;
|
||||
}
|
||||
|
||||
// Mutator
|
||||
void set (const T& v)
|
||||
{
|
||||
value_ref = v;
|
||||
}
|
||||
|
||||
// Inquiries
|
||||
bool isInitializedCopy()
|
||||
{
|
||||
return bool( &value == &value_ref );
|
||||
}
|
||||
|
||||
bool isInitializedReference()
|
||||
{
|
||||
return ! isInitializedCopy();
|
||||
}
|
||||
|
||||
// Friend Non-member operator functions
|
||||
friend std::ostream& operator << (std::ostream &os, const FData& data)
|
||||
{
|
||||
os << data.value_ref;
|
||||
return os;
|
||||
}
|
||||
|
||||
private:
|
||||
// Data members
|
||||
T value{};
|
||||
T& value_ref;
|
||||
};
|
||||
|
||||
// non-member functions
|
||||
//----------------------------------------------------------------------
|
||||
namespace internal
|
||||
|
@ -254,6 +109,162 @@ constexpr FData<clean_fdata_t<T>>* makeFData (T&& data)
|
|||
return new FData<clean_fdata_t<T>>(std::forward<T>(data));
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// class FDataAccess
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
class FDataAccess
|
||||
{
|
||||
public:
|
||||
// Constructor
|
||||
FDataAccess();
|
||||
|
||||
// Destructor
|
||||
virtual ~FDataAccess();
|
||||
|
||||
// Accessors
|
||||
virtual const FString getClassName() const
|
||||
{
|
||||
return "FDataAccess";
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
clean_fdata_t<T>& get()
|
||||
{
|
||||
return static_cast<FData<clean_fdata_t<T>>&>(*this).get();
|
||||
}
|
||||
|
||||
// Mutator
|
||||
template <typename T
|
||||
, typename V>
|
||||
void set (V& data)
|
||||
{
|
||||
static_cast<FData<T>&>(*this).set(std::forward<V>(data));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// class FData
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
template <typename T>
|
||||
class FData : public FDataAccess
|
||||
{
|
||||
public:
|
||||
// Constructors
|
||||
explicit FData (T& v) // constructor
|
||||
: value_ref{v}
|
||||
{ }
|
||||
|
||||
explicit FData (T&& v) // constructor
|
||||
: value{std::move(v)}
|
||||
, value_ref{value}
|
||||
{ }
|
||||
|
||||
// Destructor
|
||||
~FData() override
|
||||
{ }
|
||||
|
||||
FData (const FData& d) // Copy constructor
|
||||
: value{d.value}
|
||||
, value_ref{d.isInitializedCopy() ? std::ref(value) : d.value_ref}
|
||||
{ }
|
||||
|
||||
FData (FData&& d) noexcept // Move constructor
|
||||
: value{std::move(d.value)}
|
||||
, value_ref{d.isInitializedCopy() ? std::ref(value) : std::move(d.value_ref)}
|
||||
{ }
|
||||
|
||||
// Overloaded operators
|
||||
FData& operator = (const FData& d) // Copy assignment operator (=)
|
||||
{
|
||||
if ( &d != this )
|
||||
{
|
||||
value = d.value;
|
||||
|
||||
if ( d.isInitializedCopy() )
|
||||
value_ref = value;
|
||||
else
|
||||
value_ref = d.value_ref;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
FData& operator = (FData&& d) noexcept // Move assignment operator (=)
|
||||
{
|
||||
if ( &d != this )
|
||||
{
|
||||
value = std::move(d.value);
|
||||
|
||||
if ( d.isInitializedCopy() )
|
||||
value_ref = value;
|
||||
else
|
||||
value_ref = std::move(d.value_ref);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
T operator () () const
|
||||
{
|
||||
return value_ref;
|
||||
}
|
||||
|
||||
explicit operator T () const
|
||||
{
|
||||
return value_ref;
|
||||
}
|
||||
|
||||
FData& operator << (const T& v)
|
||||
{
|
||||
value_ref.get() = v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Accessors
|
||||
const FString getClassName() const override
|
||||
{
|
||||
return "FData";
|
||||
}
|
||||
|
||||
T& get() const
|
||||
{
|
||||
return value_ref;
|
||||
}
|
||||
|
||||
// Mutator
|
||||
void set (const T& v)
|
||||
{
|
||||
value_ref.get() = v;
|
||||
}
|
||||
|
||||
// Inquiries
|
||||
bool isInitializedCopy() const
|
||||
{
|
||||
return bool( (void*)&value == (void*)&value_ref.get() );
|
||||
}
|
||||
|
||||
bool isInitializedReference() const
|
||||
{
|
||||
return ! isInitializedCopy();
|
||||
}
|
||||
|
||||
// Friend Non-member operator functions
|
||||
friend std::ostream& operator << (std::ostream &os, const FData& data)
|
||||
{
|
||||
os << data.value_ref.get();
|
||||
return os;
|
||||
}
|
||||
|
||||
private:
|
||||
// Data members
|
||||
T value{};
|
||||
std::reference_wrapper<T> value_ref;
|
||||
};
|
||||
|
||||
} // namespace finalcut
|
||||
|
||||
#endif // FDATA_H
|
||||
|
|
|
@ -46,6 +46,12 @@ long int my_function2 (long int i)
|
|||
return 2 * i;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
long int my_function3 (long int i)
|
||||
{
|
||||
return 3 * i;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// class FDataTest
|
||||
|
@ -60,6 +66,10 @@ class FDataTest : public CPPUNIT_NS::TestFixture
|
|||
protected:
|
||||
void classNameTest();
|
||||
void fdataTest();
|
||||
void copyConstructorTest();
|
||||
void moveConstructorTest();
|
||||
void copyAssignmentTest();
|
||||
void moveAssignmentTest();
|
||||
void makeFDataTest();
|
||||
|
||||
private:
|
||||
|
@ -69,6 +79,10 @@ class FDataTest : public CPPUNIT_NS::TestFixture
|
|||
// Add a methods to the test suite
|
||||
CPPUNIT_TEST (classNameTest);
|
||||
CPPUNIT_TEST (fdataTest);
|
||||
CPPUNIT_TEST (copyConstructorTest);
|
||||
CPPUNIT_TEST (moveConstructorTest);
|
||||
CPPUNIT_TEST (copyAssignmentTest);
|
||||
CPPUNIT_TEST (moveAssignmentTest);
|
||||
CPPUNIT_TEST (makeFDataTest);
|
||||
|
||||
// End of test suite definition
|
||||
|
@ -116,7 +130,7 @@ void FDataTest::fdataTest()
|
|||
|
||||
// int value
|
||||
int integer_value = 10;
|
||||
auto data2 = finalcut::FData<int>(integer_value);
|
||||
auto data2 = finalcut::FData<int>(std::ref(integer_value));
|
||||
CPPUNIT_ASSERT ( ! data2.isInitializedCopy() );
|
||||
CPPUNIT_ASSERT ( data2.isInitializedReference() );
|
||||
stream.clear();
|
||||
|
@ -203,11 +217,117 @@ void FDataTest::fdataTest()
|
|||
CPPUNIT_ASSERT ( data7.get() == "xyz" );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void FDataTest::copyConstructorTest()
|
||||
{
|
||||
// value copy
|
||||
auto data1 = finalcut::FData<int>(2);
|
||||
CPPUNIT_ASSERT ( data1.isInitializedCopy() );
|
||||
CPPUNIT_ASSERT ( data1.get() == 2 );
|
||||
auto data2 = finalcut::FData<int>(data1);
|
||||
CPPUNIT_ASSERT ( data2.isInitializedCopy() );
|
||||
data1.get()++;
|
||||
CPPUNIT_ASSERT ( data1.get() == 3 );
|
||||
CPPUNIT_ASSERT ( data2.get() == 2 );
|
||||
|
||||
// reference copy
|
||||
uInt n = 100;
|
||||
auto data3 = finalcut::FData<uInt>(n);
|
||||
CPPUNIT_ASSERT ( data3.isInitializedReference() );
|
||||
CPPUNIT_ASSERT ( data3.get() == 100 );
|
||||
auto data4 = finalcut::FData<uInt>(data3);
|
||||
CPPUNIT_ASSERT ( data4.isInitializedReference() );
|
||||
data3.get()--;
|
||||
CPPUNIT_ASSERT ( data3.get() == 99 );
|
||||
CPPUNIT_ASSERT ( data4.get() == 99 );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void FDataTest::moveConstructorTest()
|
||||
{
|
||||
// value copy
|
||||
auto data1 = finalcut::FData<int>(-5);
|
||||
CPPUNIT_ASSERT ( data1.isInitializedCopy() );
|
||||
CPPUNIT_ASSERT ( data1.get() == -5 );
|
||||
auto data2 = finalcut::FData<int>(std::move(data1));
|
||||
CPPUNIT_ASSERT ( data2.isInitializedCopy() );
|
||||
data1.get() += 10;
|
||||
CPPUNIT_ASSERT ( data1.get() == 5 );
|
||||
CPPUNIT_ASSERT ( data2.get() == -5 );
|
||||
|
||||
// reference copy
|
||||
long int n = 0xfffffff;
|
||||
auto data3 = finalcut::FData<long int>(n);
|
||||
CPPUNIT_ASSERT ( data3.isInitializedReference() );
|
||||
CPPUNIT_ASSERT ( data3.get() == 0xfffffff );
|
||||
auto data4 = finalcut::FData<long int>(std::move(data3));
|
||||
CPPUNIT_ASSERT ( data4.isInitializedReference() );
|
||||
data3.get()++;
|
||||
CPPUNIT_ASSERT ( data3.get() == 0x10000000 );
|
||||
CPPUNIT_ASSERT ( data4.get() == 0x10000000 );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void FDataTest::copyAssignmentTest()
|
||||
{
|
||||
// value copy
|
||||
auto data1 = finalcut::FData<char>(123);
|
||||
CPPUNIT_ASSERT ( data1.isInitializedCopy() );
|
||||
CPPUNIT_ASSERT ( data1.get() == 123 );
|
||||
finalcut::FData<char> data2{0};
|
||||
data2 = data1;
|
||||
CPPUNIT_ASSERT ( data2.isInitializedCopy() );
|
||||
data1.get() -= 100;
|
||||
CPPUNIT_ASSERT ( data1.get() == 23 );
|
||||
CPPUNIT_ASSERT ( data2.get() == 123 );
|
||||
|
||||
// reference copy
|
||||
double c = 299792458.0; // Speed of light
|
||||
auto data3 = finalcut::FData<double>(c);
|
||||
CPPUNIT_ASSERT ( data3.isInitializedReference() );
|
||||
CPPUNIT_ASSERT ( data3.get() == 299792458 );
|
||||
finalcut::FData<double> data4{0.0};
|
||||
data4 = data3;
|
||||
CPPUNIT_ASSERT ( data4.isInitializedReference() );
|
||||
data4.get() -= 343.2; // Speed of sound
|
||||
|
||||
CPPUNIT_ASSERT ( data3.get() == 299792114.8 );
|
||||
CPPUNIT_ASSERT ( data4.get() == 299792114.8 );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void FDataTest::moveAssignmentTest()
|
||||
{
|
||||
// value copy
|
||||
auto data1 = finalcut::FData<float>(9.81F);
|
||||
CPPUNIT_ASSERT ( data1.isInitializedCopy() );
|
||||
CPPUNIT_ASSERT ( data1.get() == 9.81F );
|
||||
finalcut::FData<float> data2{0};
|
||||
data2 = std::move(data1);
|
||||
CPPUNIT_ASSERT ( data2.isInitializedCopy() );
|
||||
data1.get() -= 0.81;
|
||||
CPPUNIT_ASSERT ( data1.get() == 9.0F );
|
||||
CPPUNIT_ASSERT ( data2.get() == 9.81F );
|
||||
|
||||
// reference copy
|
||||
auto au = 149597870700LL; // Astronomical unit
|
||||
auto data3 = finalcut::FData<long long int>(au);
|
||||
CPPUNIT_ASSERT ( data3.isInitializedReference() );
|
||||
CPPUNIT_ASSERT ( data3.get() == 149597870700LL );
|
||||
finalcut::FData<long long int> data4{0};
|
||||
data4 = std::move(data3);
|
||||
CPPUNIT_ASSERT ( data4.isInitializedReference() );
|
||||
data4.get() /= 2LL;
|
||||
CPPUNIT_ASSERT ( data3.get() == 74798935350LL );
|
||||
CPPUNIT_ASSERT ( data4.get() == 74798935350LL );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void FDataTest::makeFDataTest()
|
||||
{
|
||||
finalcut::FDataAccess* data_pointer{nullptr};
|
||||
|
||||
// Array
|
||||
using ThreeInts = int[3];
|
||||
ThreeInts int_array{2, 1, 4};
|
||||
data_pointer = finalcut::makeFData(std::move(int_array));
|
||||
|
@ -215,10 +335,12 @@ void FDataTest::makeFDataTest()
|
|||
CPPUNIT_ASSERT ( ints[0] == 2 );
|
||||
CPPUNIT_ASSERT ( ints[1] == 1 );
|
||||
CPPUNIT_ASSERT ( ints[2] == 4 );
|
||||
delete data_pointer;
|
||||
|
||||
// Integer
|
||||
int n = 9;
|
||||
data_pointer = finalcut::makeFData(std::move(n));
|
||||
auto data = static_cast<finalcut::FData<int>&&>(*data_pointer);
|
||||
auto& data = static_cast<finalcut::FData<int>&>(*data_pointer);
|
||||
CPPUNIT_ASSERT ( data.isInitializedCopy() );
|
||||
CPPUNIT_ASSERT ( ! data.isInitializedReference() );
|
||||
auto& n2 = data.get();
|
||||
|
@ -226,10 +348,18 @@ void FDataTest::makeFDataTest()
|
|||
n2++;
|
||||
CPPUNIT_ASSERT ( n2 == 10 );
|
||||
CPPUNIT_ASSERT ( data() == 10 );
|
||||
CPPUNIT_ASSERT ( data_pointer->get<int>() == 10 );
|
||||
//data_pointer->set<int>(33);
|
||||
//CPPUNIT_ASSERT ( data_pointer->get<int>() == 33 );
|
||||
delete data_pointer;
|
||||
|
||||
data_pointer = finalcut::makeFData(std::move(my_function2));
|
||||
// Function
|
||||
data_pointer = finalcut::makeFData(my_function2);
|
||||
const auto& func = static_cast<finalcut::FData<finalcut::clean_fdata_t<long int (*) (long int)>>&>(*data_pointer).get();
|
||||
CPPUNIT_ASSERT ( func(128) == 256 );
|
||||
//data_pointer->set<long int (*) (long int)>(&my_function3);
|
||||
//PUNIT_ASSERT ( func(128) == 384 );
|
||||
delete data_pointer;
|
||||
}
|
||||
|
||||
// Put the test suite in the registry
|
||||
|
|
Loading…
Reference in New Issue