FData improvements

This commit is contained in:
Markus Gans 2020-09-26 01:59:58 +02:00
parent b15a665729
commit 4478948bc7
3 changed files with 292 additions and 148 deletions

View File

@ -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

View File

@ -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

View File

@ -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