Added emplace functions to etl::variant

This commit is contained in:
John Wellbelove 2018-02-04 17:34:51 +00:00
parent c43adc7df3
commit 1dd1ffc4e4
4 changed files with 248 additions and 11 deletions

View File

@ -1,5 +1,5 @@
name=Embedded Template Library
version=10.16.1
version=10.17.0
author= John Wellbelove <john.wellbelove@etlcpp.com>
maintainer=John Wellbelove <john.wellbelove@etlcpp.com>
sentence=A C++ template library tailored for embedded systems.

View File

@ -112,6 +112,18 @@ namespace etl
typename T8 = __private_variant__::no_type<8> >
class variant
{
public:
//***************************************************************************
/// The type used for ids.
//***************************************************************************
typedef uint_least8_t type_id_t;
//***************************************************************************
/// The id a unsupported types.
//***************************************************************************
static const type_id_t UNSUPPORTED_TYPE_ID = integral_limits<type_id_t>::max;
private:
// All types of variant are friends.
@ -133,16 +145,6 @@ namespace etl
//***************************************************************************
static const size_t ALIGNMENT = etl::largest_alignment<T1, T2, T3, T4, T5, T6, T7, T8>::value;
//***************************************************************************
/// The type used for ids.
//***************************************************************************
typedef uint_least8_t type_id_t;
//***************************************************************************
/// The id a unsupported types.
//***************************************************************************
static const type_id_t UNSUPPORTED_TYPE_ID = integral_limits<type_id_t>::max;
//***************************************************************************
/// Short form of no_type placeholders.
//***************************************************************************
@ -701,6 +703,84 @@ namespace etl
type_id = other.type_id;
}
#if !ETL_CPP11_SUPPORTED
//***************************************************************************
/// Emplace with one constructor parameter.
//***************************************************************************
template <typename T, typename TP1>
T& emplace(const TP1& value1)
{
STATIC_ASSERT(Type_Is_Supported<T>::value, "Unsupported type");
destruct_current();
::new (static_cast<T*>(data)) T(value1);
type_id = Type_Id_Lookup<T>::type_id;
return *static_cast<T*>(data);
}
//***************************************************************************
/// Emplace with two constructor parameters.
//***************************************************************************
template <typename T, typename TP1, typename TP2>
T& emplace(const TP1& value1, const TP2& value2)
{
STATIC_ASSERT(Type_Is_Supported<T>::value, "Unsupported type");
destruct_current();
::new (static_cast<T*>(data)) T(value1, value2);
type_id = Type_Id_Lookup<T>::type_id;
return *static_cast<T*>(data);
}
//***************************************************************************
/// Emplace with three constructor parameters.
//***************************************************************************
template <typename T, typename TP1, typename TP2, typename TP3>
T& emplace(const TP1& value1, const TP2& value2, const TP3& value3)
{
STATIC_ASSERT(Type_Is_Supported<T>::value, "Unsupported type");
destruct_current();
::new (static_cast<T*>(data)) T(value1, value2, value3);
type_id = Type_Id_Lookup<T>::type_id;
return *static_cast<T*>(data);
}
//***************************************************************************
/// Emplace with four constructor parameters.
//***************************************************************************
template <typename T, typename TP1, typename TP2, typename TP3, typename TP4>
T& emplace(const TP1& value1, const TP2& value2, const TP3& value3, const TP4& value4)
{
STATIC_ASSERT(Type_Is_Supported<T>::value, "Unsupported type");
destruct_current();
::new (static_cast<T*>(data)) T(value1, value2, value3, value4);
type_id = Type_Id_Lookup<T>::type_id;
return *static_cast<T*>(data);
}
#else
//*************************************************************************
/// Emplace with variadic constructor parameters.
//*************************************************************************
template <typename T, typename... Args>
T& emplace(Args&&... args)
{
STATIC_ASSERT(Type_Is_Supported<T>::value, "Unsupported type");
destruct_current();
::new (static_cast<T*>(data)) T(std::forward<Args>(args)...);
type_id = Type_Id_Lookup<T>::type_id;
return *static_cast<T*>(data);
}
#endif
//***************************************************************************
/// Assignment operator for T1 type.
///\param value The value to assign.
@ -821,6 +901,14 @@ namespace etl
return type_id == Type_Id_Lookup<T>::type_id;
}
//***************************************************************************
/// Gets the index of the type currently stored or UNSUPPORTED_TYPE_ID
//***************************************************************************
ETL_CONSTEXPR size_t index() const
{
return type_id;
}
//***************************************************************************
/// Clears the value to 'no valid stored value'.
//***************************************************************************

View File

@ -1,3 +1,7 @@
===============================================================================
10.17.0
Added emplace functions to etl::variant.
===============================================================================
10.16.1
Improved performance of emplace for value_type parameters.

View File

@ -34,6 +34,7 @@ SOFTWARE.
#include <array>
#include <vector>
#include <algorithm>
#include <string>
namespace
{
@ -99,6 +100,128 @@ namespace
// This line should compile with no errors.
test_variant_max_types variant_max;
struct D1
{
D1(const std::string& a_)
: a(a_)
{
}
std::string a;
};
struct D2
{
D2(const std::string& a_, const std::string& b_)
: a(a_),
b(b_)
{
}
std::string a;
std::string b;
};
struct D3
{
D3(const std::string& a_, const std::string& b_, const std::string& c_)
: a(a_),
b(b_),
c(c_)
{
}
std::string a;
std::string b;
std::string c;
};
struct D4
{
D4(const std::string& a_, const std::string& b_, const std::string& c_, const std::string& d_)
: a(a_),
b(b_),
c(c_),
d(d_)
{
}
std::string a;
std::string b;
std::string c;
std::string d;
};
bool operator == (const D1& lhs, const D1& rhs)
{
return (lhs.a == rhs.a);
}
bool operator == (const D2& lhs, const D2& rhs)
{
return (lhs.a == rhs.a) && (lhs.b == rhs.b);
}
bool operator == (const D3& lhs, const D3& rhs)
{
return (lhs.a == rhs.a) && (lhs.b == rhs.b) && (lhs.c == rhs.c);
}
bool operator == (const D4& lhs, const D4& rhs)
{
return (lhs.a == rhs.a) && (lhs.b == rhs.b) && (lhs.c == rhs.c) && (lhs.d == rhs.d);
}
bool operator != (const D1& lhs, const D1& rhs)
{
return !(lhs == rhs);
}
bool operator != (const D2& lhs, const D2& rhs)
{
return !(lhs == rhs);
}
bool operator != (const D3& lhs, const D3& rhs)
{
return !(lhs == rhs);
}
bool operator != (const D4& lhs, const D4& rhs)
{
return !(lhs == rhs);
}
std::ostream& operator <<(std::ostream& os, const D1& d1)
{
os << d1.a;
return os;
}
std::ostream& operator <<(std::ostream& os, const D2& d2)
{
os << d2.a << " " << d2.b;
return os;
}
std::ostream& operator <<(std::ostream& os, const D3& d3)
{
os << d3.a << " " << d3.b << " " << d3.c;
return os;
}
std::ostream& operator <<(std::ostream& os, const D4& d4)
{
os << d4.a << " " << d4.b << " " << d4.c << " " << d4.d;
return os;
}
typedef etl::variant<D1, D2, D3, D4> test_variant_emplace;
SUITE(test_variant)
{
TEST(test_alignment)
@ -666,5 +789,27 @@ namespace
variant.upcast<base>().set();
CHECK_EQUAL(2, variant.get<derived_2>().value);
}
//*************************************************************************
TEST(TestEmplace)
{
test_variant_emplace variant;
variant.emplace<D1>("1");
CHECK(variant.is_type<D1>());
CHECK_EQUAL(D1("1"), variant.get<D1>());
variant.emplace<D2>("1", "2");
CHECK(variant.is_type<D2>());
CHECK_EQUAL(D2("1", "2"), variant.get<D2>());
variant.emplace<D3>("1", "2", "3");
CHECK(variant.is_type<D3>());
CHECK_EQUAL(D3("1", "2", "3"), variant.get<D3>());
variant.emplace<D4>("1", "2", "3", "4");
CHECK(variant.is_type<D4>());
CHECK_EQUAL(D4("1", "2", "3", "4"), variant.get<D4>());
}
};
}