Skip to content
Snippets Groups Projects
Commit 89518f29 authored by Jan Trávníček's avatar Jan Trávníček
Browse files

add callback acceptor to variant

parent 6badb784
No related branches found
No related tags found
No related merge requests found
......@@ -61,6 +61,25 @@ struct variant_helper;
*/
template<typename F, typename... Ts>
struct variant_helper<F, Ts...> {
/**
* \brief
* Implementation of call passing for type F (if the type F is currently stored inside the variant).
*
* \tparam Result the callback result
* \tparam Callable type of callback to execute
*
* \param id the representation of type stored inside the variant
* \param data storage occupied by value stored in the variant
* \param callable the callback to execute
*/
template < class Result, class Callable >
inline static Result call ( ext::type_index id, const void * data, Callable callable ) {
if (id == ext::type_index ( typeid ( F ) ) )
return callable ( * reinterpret_cast < const F * > ( data ) );
else
return variant_helper < Ts ... >::template call < Result > ( id, data, callable );
}
/**
* \brief
* Implementation of destructor for type F (if the type F is currently stored inside the variant)
......@@ -69,7 +88,7 @@ struct variant_helper<F, Ts...> {
* \param data storage occupied by value stored in the variant
*/
inline static void destroy(ext::type_index id, void * data) {
if (id == ext::type_index ( ext::type_index ( typeid ( F ) ) ) )
if (id == ext::type_index ( typeid ( F ) ) )
reinterpret_cast<F*>(data)->~F();
else
variant_helper<Ts...>::destroy(id, data);
......@@ -105,34 +124,6 @@ struct variant_helper<F, Ts...> {
variant_helper<Ts...>::move(old_t, old_v, new_v);
}
 
/**
* \brief
* Implementation of operator << for type F (if the type F is currently stored inside the variant)
*
* \param id the representation of type stored inside the variant
* \param data storage occupied by value stored in the variant
*/
inline static void print(std::ostream& out, ext::type_index id, const void* data) {
if (id == ext::type_index ( typeid ( F ) ))
out << *reinterpret_cast<const F*>(data);
else
variant_helper<Ts...>::print(out, id, data);
}
/**
* \brief
* Implementation of to_string for type F (if the type F is currently stored inside the variant)
*
* \param id the representation of type stored inside the variant
* \param data storage occupied by value stored in the variant
*/
inline static std::string string(ext::type_index id, const void* data) {
if (id == ext::type_index ( typeid ( F ) ))
return ext::to_string ( *reinterpret_cast<const F*>(data) );
else
return variant_helper<Ts...>::string(id, data);
}
/**
* \brief
* Implementation of three way comparison for type F (if the type F is currently stored inside the variant)
......@@ -161,6 +152,25 @@ struct variant_helper<F, Ts...> {
*/
template<typename... Ts>
struct variant_helper<void, Ts...> {
/**
* \brief
* Implementation of call passing for type F (if the type F is currently stored inside the variant).
*
* \tparam Result the callback result
* \tparam Callable type of callback to execute
*
* \param id the representation of type stored inside the variant
* \param data storage occupied by value stored in the variant
* \param callable the callback to execute
*/
template < class Result, class Callable >
inline static Result call ( ext::type_index id, const void * data, Callable callable ) {
if (id == ext::type_index ( typeid ( void ) ) )
return callable ( );
else
return variant_helper < Ts ... >::template call < Result > ( id, data, callable );
}
/**
* \brief
* Implementation of destructor for void type (if the void type is currently stored inside the variant)
......@@ -199,34 +209,6 @@ struct variant_helper<void, Ts...> {
variant_helper<Ts...>::move(old_t, old_v, new_v);
}
 
/**
* \brief
* Implementation of operator << for void type (if the void type is currently stored inside the variant)
*
* \param id the representation of type stored inside the variant
* \param data storage occupied by value stored in the variant
*/
inline static void print(std::ostream& out, ext::type_index id, const void* data) {
if (id == ext::type_index ( typeid ( void ) ))
out << "void";
else
variant_helper<Ts...>::print(out, id, data);
}
/**
* \brief
* Implementation of to_string for void type (if the void type is currently stored inside the variant)
*
* \param id the representation of type stored inside the variant
* \param data storage occupied by value stored in the variant
*/
inline static std::string string(ext::type_index id, const void* data) {
if (id == ext::type_index ( typeid ( void ) ))
return "void";
else
return variant_helper<Ts...>::string(id, data);
}
/**
* \brief
* Implementation of three way comparison for void type (if the void type is currently stored inside the variant)
......@@ -254,45 +236,38 @@ template < > struct variant_helper < > {
 
/**
* \brief
* Destructor helper when the pack of types of the variant was depleted.
*
* Does nothing.
*/
inline static void destroy(ext::type_index, void *) { }
/**
* \brief
* Copy constructor helper when the pack of types of the variant was depleted.
* Implementation of call passing for type F (if the type F is currently stored inside the variant).
*
* Does nothing.
*/
inline static void copy(ext::type_index, const void *, void *) { }
template < class Result, class Callable >
inline static Result call ( ext::type_index, const void *, Callable ) {
throw std::logic_error ( "Out of types of variant." );
}
 
/**
* \brief
* Move constructor helper when the pack of types of the variant was depleted.
* Destructor helper when the pack of types of the variant was depleted.
*
* Does nothing.
*/
inline static void move(ext::type_index, void *, void *) { }
inline static void destroy(ext::type_index, void *) { }
 
/**
* \brief
* Print to stream helper when the pack of types of the variant was depleted.
* Copy constructor helper when the pack of types of the variant was depleted.
*
* Does nothing.
*/
inline static void print(std::ostream&, ext::type_index, const void *) { }
inline static void copy(ext::type_index, const void *, void *) { }
 
/**
* \brief
* To string helper when the pack of types of the variant was depleted.
* Move constructor helper when the pack of types of the variant was depleted.
*
* Does nothing.
*
* \return empty string
*/
inline static std::string string(ext::type_index, const void *) { return ""; }
inline static void move(ext::type_index, void *, void *) { }
 
/**
* \brief
......@@ -457,6 +432,71 @@ class variant : public variant_base < max ( SizeOf < Ts >::size ... ), max ( Ali
*/
using helper_t = variant_helper<Ts...>;
 
/**
* Internal variant to string callback implementation.
*/
class VariantToString {
public:
/**
* The callback for types different from void
*
* \tparam T the accepted tye
*
* \param value the accepted value
*
* \return string representation of the value
*/
template < class T >
std::string operator ( ) ( const T & value ) const {
return ext::to_string ( value );
}
/**
* The callback for void type
*
* \return string "void"
*/
std::string operator ( ) ( ) const {
return "void";
}
};
/**
* Internal variant to ostream callback implementation.
*/
class VariantToStream {
/**
* The stream to print to.
*/
std::ostream & m_out;
public:
/**
* Constructor of the variant to stream callback.
*
* \param out the output stream to use in function call operators.
*/
VariantToStream ( std::ostream & out ) : m_out ( out ) {
}
/**
* The callback for types different from void
*
* \tparam T the accepted tye
*
* \param value the accepted value
*/
template < class T >
void operator ( ) ( const T & value ) {
m_out << value;
}
/**
* The callback for void type, printing "void" to the stream
*/
void operator ( ) ( ) {
m_out << "void";
}
};
public:
/**
* \brief
......@@ -720,6 +760,22 @@ public:
helper_t::destroy(this->type_id, &this->data);
}
 
/**
* \brief
* Callback executor on current variant value.
*
* \tparam Result the uniform result type
* \tparam Callable type of callable able to accept any variant type.
*
* \param callable object of callable type able to accept any variant type via function call operator. The possible void type is represented by call with no parameters
*
* \return the result of the callable on the current variable type
*/
template < class Result, class Callable >
Result call ( Callable callable ) const {
return helper_t::template call < Result > ( this->type_id, & this->data, callable );
}
/**
* \brief
* Operator to print the variant to the output stream.
......@@ -730,7 +786,7 @@ public:
* \return the output stream from the \p out
*/
friend std::ostream & operator << ( std::ostream & out, const variant < Ts ... > & obj ) {
helper_t::print(out, obj.type_id, &obj.data);
obj.call < void > ( VariantToStream ( out ) );
return out;
}
 
......@@ -741,7 +797,7 @@ public:
* \return string representation of the variant
*/
explicit operator std::string() const {
return helper_t::string(this->type_id, &this->data);
return this->call < std::string > ( VariantToString ( ) );
}
 
/**
......@@ -969,6 +1025,22 @@ public:
return std::move ( m_value );
}
 
/**
* \brief
* Callback executor on current variant value.
*
* \tparam Result the uniform result type
* \tparam Callable type of callable able to accept any variant type.
*
* \param callable object of callable type able to accept any variant type via function call operator. The possible void type is represented by call with no parameters
*
* \return the result of the callable on the current variable type
*/
template < class Result, class Callable >
Result call ( Callable callable ) const {
return callable ( m_value );
}
/**
* \brief
* Operator to print the variant to the output stream.
......@@ -1126,6 +1198,22 @@ public:
typename std::enable_if < std::is_same < T, void >::value, void >::type set ( ) {
}
 
/**
* \brief
* Callback executor on current variant value.
*
* \tparam Result the uniform result type
* \tparam Callable type of callable able to accept any variant type.
*
* \param callable object of callable type able to accept any variant type via function call operator. The possible void type is represented by call with no parameters
*
* \return the result of the callable on the current variable type
*/
template < class Result, class Callable >
Result call ( Callable callable ) const {
return callable ( );
}
/**
* \brief
* Operator to print the variant to the output stream.
......
......@@ -3,6 +3,7 @@
#include <alib/set>
#include <alib/algorithm>
#include <alib/map>
#include <sstream>
 
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( VariantTest, "bits" );
CPPUNIT_TEST_SUITE_REGISTRATION( VariantTest );
......@@ -57,6 +58,12 @@ void VariantTest::testVariant() {
CPPUNIT_ASSERT( (e < d) == false );
 
CPPUNIT_ASSERT( (e == d) == true );
CPPUNIT_ASSERT ( ( ( std::string ) e ) == "43" );
std::stringstream ss;
ss << e;
CPPUNIT_ASSERT ( ss.str ( ) == "43" );
}
 
void VariantTest::testVariantSet() {
......
......@@ -3,6 +3,7 @@
 
#include <cppunit/extensions/HelperMacros.h>
#include <alib/compare>
#include <alib/string>
 
class VariantTest : public CppUnit::TestFixture
{
......@@ -60,6 +61,10 @@ struct test {
out << *(other.holder);
return out;
}
operator std::string ( ) const {
return ext::to_string ( * holder );
}
};
 
struct test2 {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment