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

change std::variant to have specific constructors

parent 1442ea47
No related branches found
No related tags found
No related merge requests found
......@@ -526,35 +526,33 @@ alphabet::Symbol AutomatonFromXMLParser::parseTransitionOutputSymbol(std::list<s
std::variant<string::Epsilon, alphabet::Symbol> AutomatonFromXMLParser::parseTransitionInputEpsilonSymbol(std::list<sax::Token>& input) const {
popToken(input, sax::Token::TokenType::START_ELEMENT, "input");
std::variant<string::Epsilon, alphabet::Symbol> result;
if(isToken(input, sax::Token::TokenType::START_ELEMENT, "epsilon")) {
result.set<string::Epsilon>(string::Epsilon());
std::variant<string::Epsilon, alphabet::Symbol> result(string::Epsilon::EPSILON);
input.pop_front();
popToken(input, sax::Token::TokenType::END_ELEMENT, "epsilon");
popToken(input, sax::Token::TokenType::END_ELEMENT, "input");
return result;
} else {
result.set<alphabet::Symbol>(alib::FromXMLParsers::symbolParser.parse(input));
std::variant<string::Epsilon, alphabet::Symbol> result(alib::FromXMLParsers::symbolParser.parse(input));
popToken(input, sax::Token::TokenType::END_ELEMENT, "input");
return result;
}
popToken(input, sax::Token::TokenType::END_ELEMENT, "input");
return result;
}
 
std::variant<string::Epsilon, alphabet::Symbol> AutomatonFromXMLParser::parseTransitionOutputEpsilonSymbol(std::list<sax::Token>& input) const {
popToken(input, sax::Token::TokenType::START_ELEMENT, "output");
std::variant<string::Epsilon, alphabet::Symbol> result;
if(isToken(input, sax::Token::TokenType::START_ELEMENT, "epsilon")) {
result.set<string::Epsilon>(string::Epsilon());
std::variant<string::Epsilon, alphabet::Symbol> result(string::Epsilon::EPSILON);
input.pop_front();
popToken(input, sax::Token::TokenType::END_ELEMENT, "epsilon");
popToken(input, sax::Token::TokenType::END_ELEMENT, "output");
return result;
} else {
result.set<alphabet::Symbol>(alib::FromXMLParsers::symbolParser.parse(input));
std::variant<string::Epsilon, alphabet::Symbol> result(alib::FromXMLParsers::symbolParser.parse(input));
popToken(input, sax::Token::TokenType::END_ELEMENT, "output");
return result;
}
popToken(input, sax::Token::TokenType::END_ELEMENT, "output");
return result;
}
 
string::String AutomatonFromXMLParser::parseTransitionInputString(std::list<sax::Token>& input) const {
......
......@@ -38,8 +38,7 @@ bool EpsilonNFA::removeState(const State& state) {
}
 
bool EpsilonNFA::removeInputSymbol(const alphabet::Symbol& symbol) {
std::variant<string::Epsilon, alphabet::Symbol> inputVariant;
inputVariant.set<alphabet::Symbol>(symbol);
std::variant<string::Epsilon, alphabet::Symbol> inputVariant(symbol);
for (std::map<std::pair<State, std::variant<string::Epsilon, alphabet::Symbol> >, std::set<State> >::const_iterator transition = transitions.begin(); transition != transitions.end();
transition++) {
if (transition->first.second.is<alphabet::Symbol>() && transition->first.second.get<alphabet::Symbol>() == symbol)
......@@ -66,28 +65,24 @@ bool EpsilonNFA::addTransition(const State& from, const std::variant<string::Eps
}
 
bool EpsilonNFA::addTransition(const State& from, const alphabet::Symbol& input, const State& to) {
std::variant<string::Epsilon, alphabet::Symbol> inputVariant;
inputVariant.set<alphabet::Symbol>(input);
std::variant<string::Epsilon, alphabet::Symbol> inputVariant(input);
return addTransition(from, inputVariant, to);
}
 
bool EpsilonNFA::addTransition(const State& from, const State& to) {
std::variant<string::Epsilon, alphabet::Symbol> inputVariant;
inputVariant.set<string::Epsilon>(string::Epsilon());
std::variant<string::Epsilon, alphabet::Symbol> inputVariant(string::Epsilon::EPSILON);
return addTransition(from, inputVariant, to);
}
 
bool EpsilonNFA::removeTransition(const State& from, const alphabet::Symbol& input, const State& to) {
std::variant<string::Epsilon, alphabet::Symbol> inputVariant;
inputVariant.set<alphabet::Symbol>(input);
std::variant<string::Epsilon, alphabet::Symbol> inputVariant(input);
std::pair<State, std::variant<string::Epsilon, alphabet::Symbol> > key = std::make_pair(from, inputVariant);
return transitions[key].erase(to);
}
 
bool EpsilonNFA::removeTransition(const State& from, const State& to) {
std::variant<string::Epsilon, alphabet::Symbol> inputVariant;
inputVariant.set<string::Epsilon>(string::Epsilon());
std::variant<string::Epsilon, alphabet::Symbol> inputVariant(string::Epsilon::EPSILON);
std::pair<State, std::variant<string::Epsilon, alphabet::Symbol> > key = std::make_pair(from, inputVariant);
return transitions[key].erase(to);
......
......@@ -78,11 +78,10 @@ EpsilonNFA FiniteAutomatonFromStringParser::parseEpsilonNFA() {
alphabet::Symbol symbol = m_SymbolParser.parse();
res.addInputSymbol(symbol);
 
std::variant<string::Epsilon, alphabet::Symbol> symbolVariant;
symbolVariant.set<alphabet::Symbol>(symbol);
std::variant<string::Epsilon, alphabet::Symbol> symbolVariant(symbol);
symbols.push_back(symbolVariant);
} else if(token.type == FiniteAutomatonFromStringLexer::TokenType::EPSILON) {
symbols.push_back(std::variant<string::Epsilon, alphabet::Symbol>());
symbols.push_back(std::variant<string::Epsilon, alphabet::Symbol>(string::Epsilon::EPSILON));
}
 
next() || m_SymbolParser.first() || m_SymbolParser.m_LabelParser.first();
......
......@@ -102,14 +102,12 @@ bool NPDA::addTransition(const State& from, const std::variant<string::Epsilon,
}
 
bool NPDA::addTransition(const State& from, const alphabet::Symbol& input, const std::vector<alphabet::Symbol>& pop, const State& to, const std::vector<alphabet::Symbol>& push) {
std::variant<string::Epsilon, alphabet::Symbol> inputVariant;
inputVariant.set<alphabet::Symbol>(input);
std::variant<string::Epsilon, alphabet::Symbol> inputVariant(input);
return addTransition(from, inputVariant, pop, to, push);
}
 
bool NPDA::addTransition(const State& from, const std::vector<alphabet::Symbol>& pop, const State& to, const std::vector<alphabet::Symbol>& push) {
std::variant<string::Epsilon, alphabet::Symbol> inputVariant;
inputVariant.set<string::Epsilon>(string::Epsilon::EPSILON);
std::variant<string::Epsilon, alphabet::Symbol> inputVariant(string::Epsilon::EPSILON);
return addTransition(from, inputVariant, pop, to, push);
}
 
......@@ -121,14 +119,12 @@ bool NPDA::removeTransition(const State& from, const std::variant<string::Epsilo
}
 
bool NPDA::removeTransition(const State& from, const alphabet::Symbol& input, const std::vector<alphabet::Symbol>& pop, const State& to, const std::vector<alphabet::Symbol>& push) {
std::variant<string::Epsilon, alphabet::Symbol> inputVariant;
inputVariant.set<alphabet::Symbol>(input);
std::variant<string::Epsilon, alphabet::Symbol> inputVariant(input);
return removeTransition(from, inputVariant, pop, to, push);
}
 
bool NPDA::removeTransition(const State& from, const std::vector<alphabet::Symbol>& pop, const State& to, const std::vector<alphabet::Symbol>& push) {
std::variant<string::Epsilon, alphabet::Symbol> inputVariant;
inputVariant.set<string::Epsilon>(string::Epsilon::EPSILON);
std::variant<string::Epsilon, alphabet::Symbol> inputVariant(string::Epsilon::EPSILON);
return removeTransition(from, inputVariant, pop, to, push);
}
 
......
......@@ -98,14 +98,12 @@ bool SinglePopNPDA::addTransition(const State& from, const std::variant<string::
}
 
bool SinglePopNPDA::addTransition(const State& from, const alphabet::Symbol& input, const alphabet::Symbol& pop, const State& to, const std::vector<alphabet::Symbol>& push) {
std::variant<string::Epsilon, alphabet::Symbol> inputVariant;
inputVariant.set<alphabet::Symbol>(input);
std::variant<string::Epsilon, alphabet::Symbol> inputVariant(input);
return addTransition(from, inputVariant, pop, to, push);
}
 
bool SinglePopNPDA::addTransition(const State& from, const alphabet::Symbol& pop, const State& to, const std::vector<alphabet::Symbol>& push) {
std::variant<string::Epsilon, alphabet::Symbol> inputVariant;
inputVariant.set<string::Epsilon>(string::Epsilon::EPSILON);
std::variant<string::Epsilon, alphabet::Symbol> inputVariant(string::Epsilon::EPSILON);
return addTransition(from, inputVariant, pop, to, push);
}
 
......@@ -117,14 +115,12 @@ bool SinglePopNPDA::removeTransition(const State& from, const std::variant<strin
}
 
bool SinglePopNPDA::removeTransition(const State& from, const alphabet::Symbol& input, const alphabet::Symbol& pop, const State& to, const std::vector<alphabet::Symbol>& push) {
std::variant<string::Epsilon, alphabet::Symbol> inputVariant;
inputVariant.set<alphabet::Symbol>(input);
std::variant<string::Epsilon, alphabet::Symbol> inputVariant(input);
return removeTransition(from, inputVariant, pop, to, push);
}
 
bool SinglePopNPDA::removeTransition(const State& from, const alphabet::Symbol& pop, const State& to, const std::vector<alphabet::Symbol>& push) {
std::variant<string::Epsilon, alphabet::Symbol> inputVariant;
inputVariant.set<string::Epsilon>(string::Epsilon::EPSILON);
std::variant<string::Epsilon, alphabet::Symbol> inputVariant(string::Epsilon::EPSILON);
return removeTransition(from, inputVariant, pop, to, push);
}
 
......
......@@ -45,22 +45,13 @@ struct variant_helper<F, Ts...> {
variant_helper<Ts...>::destroy(id, data);
}
 
inline static bool move(size_t old_t, void * old_v, void * new_v)
{
if (old_t == typeid(F).hash_code()) {
new (new_v) F(std::move(*reinterpret_cast<F*>(old_v)));
return true;
} else
return variant_helper<Ts...>::move(old_t, old_v, new_v);
}
inline static void copy(size_t old_t, const void * old_v, void * new_v)
{
if (old_t == typeid(F).hash_code())
new (new_v) F(*reinterpret_cast<const F*>(old_v));
else
return variant_helper<Ts...>::copy(old_t, old_v, new_v);
}
}
inline static bool compareEq(size_t this_t, const void * this_v, size_t other_t, const void * other_v)
{
......@@ -93,49 +84,66 @@ struct variant_helper<F, Ts...> {
 
template<> struct variant_helper<> {
inline static void destroy(size_t, void *) { }
inline static bool move(size_t, void *, void *) { return false; }
inline static void copy(size_t, const void *, void *) { }
inline static bool compareEq(size_t, const void *, size_t, const void *) { return true; }
inline static void print(ostream&, const size_t, const void *) {}
inline static bool compareLess(size_t, const void *, size_t, const void *) { return false; }
};
 
template<typename F, typename... Ts>
struct variant {
private:
static const size_t data_size = static_max<sizeof(F), sizeof(Ts)...>::value;
static const size_t data_align = static_max<alignof(F), alignof(Ts)...>::value;
template<typename ST, typename AT, typename... Ts>
class variant_base;
 
using data_t = typename std::aligned_storage<data_size, data_align>::type;
template<typename ST, typename AT>
class variant_base<ST, AT> {
static const size_t data_size = ST::value;
static const size_t data_align = AT::value;
 
using helper_t = variant_helper<F, Ts...>;
using data_t = typename std::aligned_storage<data_size, data_align>::type;
protected:
 
size_t type_id;
data_t data;
public:
//default constructor
variant() : type_id(typeid(F).hash_code()) { new (&data) F(); }
variant_base() { this->type_id = 0; }
};
template<typename ST, typename AT, typename F, typename... Ts>
class variant_base<ST, AT, F, Ts...> : public variant_base<ST, AT, Ts...> {
protected:
variant_base() { this->type_id = 0; }
public:
using variant_base<ST, AT, Ts...>::variant_base;
variant_base(const F& value) { this->type_id = typeid(F).hash_code(); new (&this->data) F(value); }
variant_base(F&& value) { this->type_id = typeid(F).hash_code(); new (&this->data) F(std::move(value)); }
};
template<typename F, typename... Ts>
class variant : public variant_base<static_max<sizeof(F), sizeof(Ts)...>, static_max<alignof(F), alignof(Ts)...>, F, Ts...> {
using helper_t = variant_helper<F, Ts...>;
public:
using variant_base<static_max<sizeof(F), sizeof(Ts)...>, static_max<alignof(F), alignof(Ts)...>, F, Ts...>::variant_base;
 
//copy consructor
variant(const variant<F, Ts...>& old) : type_id(old.type_id)
variant(const variant<F, Ts...>& old) : variant_base<static_max<sizeof(F), sizeof(Ts)...>, static_max<alignof(F), alignof(Ts)...>, F, Ts...>()
{
helper_t::copy(old.type_id, &old.data, &data);
this->type_id = old.type_id;
helper_t::copy(old.type_id, &old.data, &this->data);
}
 
//move constructor
variant(variant<F, Ts...>&& old) : type_id(old.type_id)
variant(variant<F, Ts...>&& old) : variant_base<static_max<sizeof(F), sizeof(Ts)...>, static_max<alignof(F), alignof(Ts)...>, F, Ts...>()
{
helper_t::move(old.type_id, &old.data, &data);
new (&old.data) F();
old.type_id = typeid(F).hash_code();
std::swap(this->type_id, old.type_id);
std::swap(this->data, old.data);
}
 
//assignment operator
variant<F, Ts...>& operator= (variant<F, Ts...> old)
{
std::swap(type_id, old.type_id);
std::swap(data, old.data);
std::swap(this->type_id, old.type_id);
std::swap(this->data, old.data);
 
return *this;
}
......@@ -143,7 +151,7 @@ public:
 
bool operator== (const variant<F, Ts...>& other) const
{
return helper_t::compareEq(type_id, &data, other.type_id, &other.data);
return helper_t::compareEq(this->type_id, &this->data, other.type_id, &other.data);
}
 
bool operator!= (const variant<F, Ts...>& other) const
......@@ -153,7 +161,7 @@ public:
 
bool operator< (const variant<F, Ts...>& other) const
{
return helper_t::compareLess(type_id, &data, other.type_id, &other.data);
return helper_t::compareLess(this->type_id, &this->data, other.type_id, &other.data);
}
 
bool operator> (const variant<F, Ts...>& other) const
......@@ -173,16 +181,16 @@ public:
 
template<typename T>
bool is() const {
return (type_id == typeid(T).hash_code());
return (this->type_id == typeid(T).hash_code());
}
 
template<typename T>
void set(T&& value)
{
if(std::is_base_of_any<T, F, Ts...>::value) {
helper_t::destroy(type_id, &data);
new (&data) T(value);
type_id = typeid(T).hash_code();
helper_t::destroy(this->type_id, &this->data);
new (&this->data) T(value);
this->type_id = typeid(T).hash_code();
} else
throw std::bad_cast();
}
......@@ -191,9 +199,9 @@ public:
void set(const T& value)
{
if(std::is_base_of_any<T, F, Ts...>::value) {
helper_t::destroy(type_id, &data);
new (&data) T(value);
type_id = typeid(T).hash_code();
helper_t::destroy(this->type_id, &this->data);
new (&this->data) T(std::move(value));
this->type_id = typeid(T).hash_code();
} else
throw std::bad_cast();
}
......@@ -202,8 +210,8 @@ public:
T& get()
{
// It is a dynamic_cast-like behaviour
if (type_id == typeid(T).hash_code())
return *reinterpret_cast<T*>(&data);
if (this->type_id == typeid(T).hash_code())
return *reinterpret_cast<T*>(&this->data);
else
throw std::bad_cast();
}
......@@ -212,14 +220,14 @@ public:
const T& get() const
{
// It is a dynamic_cast-like behaviour
if (type_id == typeid(T).hash_code())
return *reinterpret_cast<const T*>(&data);
if (this->type_id == typeid(T).hash_code())
return *reinterpret_cast<const T*>(&this->data);
else
throw std::bad_cast();
}
 
~variant() {
helper_t::destroy(type_id, &data);
helper_t::destroy(this->type_id, &this->data);
}
 
friend std::ostream& operator <<(std::ostream& out, const variant<F, Ts...>& obj) {
......
......@@ -18,9 +18,7 @@ void StdTest::testIsBaseOf() {
}
 
void StdTest::testVariant() {
std::variant<int, std::string, StdTest::test> d;
d.set<int>(10);
std::variant<int, std::string, StdTest::test> d(10);
CPPUNIT_ASSERT( d.is<int>() );
CPPUNIT_ASSERT( d.get<int>() == 10 );
......@@ -47,7 +45,7 @@ void StdTest::testVariant() {
CPPUNIT_ASSERT( (e == d) == false );
d = std::variant<int, std::string, StdTest::test>();
d = std::variant<int, std::string, StdTest::test>(0);
d = e;
 
CPPUNIT_ASSERT( *(d.get<StdTest::test>().holder) == 43 );
......@@ -64,16 +62,13 @@ void StdTest::testVariantSet() {
std::string str = "abcde";
std::variant<int, std::string, StdTest::test> d;
d.set<StdTest::test>(StdTest::test());
std::variant<int, std::string, StdTest::test> d(StdTest::test {});
*(d.get<StdTest::test>().holder) = 42;
std::variant<int, std::string, StdTest::test> e(d);
std::variant<int, std::string, StdTest::test> f;
f.set<int>(5);
std::variant<int, std::string, StdTest::test> f(5);
std::variant<int, std::string, StdTest::test> g;
g.set<std::string>(str);
std::variant<int, std::string, StdTest::test> g(str);
std::set<std::variant<int, std::string, StdTest::test>> testSet;
testSet.insert(d);
......@@ -91,4 +86,7 @@ void StdTest::testVariantSet() {
if(iter->is<StdTest::test>())
CPPUNIT_ASSERT( iter->get<StdTest::test>() == tmp );
}
std::variant<StdTest::test2, std::string, StdTest::test> h("aa");
CPPUNIT_ASSERT( h.is<std::string>() );
}
......@@ -49,6 +49,12 @@ struct test {
}
};
 
struct test2 {
int i;
test2(int i) : i(i) {}
};
public:
void setUp();
void tearDown();
......@@ -58,4 +64,4 @@ public:
void testVariantSet();
};
 
#endif // VARIANT_TEST_H_
\ No newline at end of file
#endif // VARIANT_TEST_H_
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