From 08382ac53c1e5ba6dba8a5486cfb8c5a8019bf09 Mon Sep 17 00:00:00 2001 From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz> Date: Wed, 15 Oct 2014 21:34:21 +0200 Subject: [PATCH] add promoting visitor --- alib2data/src/alphabet/SymbolBase.h | 4 +- alib2data/src/automaton/AutomatonBase.h | 4 +- alib2data/src/automaton/FSM/CompactNFA.h | 4 + alib2data/src/automaton/FSM/EpsilonNFA.h | 3 + alib2data/src/automaton/FSM/ExtendedNFA.h | 5 + .../src/automaton/FSM/MultiInitialStateNFA.h | 2 + alib2data/src/automaton/FSM/NFA.cpp | 1 - alib2data/src/automaton/FSM/NFA.h | 2 + alib2data/src/container/ContainerBase.h | 4 +- alib2data/src/grammar/GrammarBase.h | 4 +- alib2data/src/label/LabelBase.h | 4 +- alib2data/src/object/ObjectBase.h | 4 +- alib2data/src/primitive/PrimitiveBase.h | 4 +- alib2data/src/regexp/RegExpBase.h | 4 +- .../src/regexp/formal/FormalRegExpElement.h | 3 +- .../regexp/unbounded/UnboundedRegExpElement.h | 3 +- alib2data/src/std/visitor.hpp | 128 ++++++++-- alib2data/src/string/StringBase.h | 5 +- alib2data/test-src/std/StdVisitorTest.cpp | 233 ++++++++++++++++++ alib2data/test-src/std/StdVisitorTest.h | 19 ++ 20 files changed, 406 insertions(+), 34 deletions(-) create mode 100644 alib2data/test-src/std/StdVisitorTest.cpp create mode 100644 alib2data/test-src/std/StdVisitorTest.h diff --git a/alib2data/src/alphabet/SymbolBase.h b/alib2data/src/alphabet/SymbolBase.h index ce062e65ae..18027e6451 100644 --- a/alib2data/src/alphabet/SymbolBase.h +++ b/alib2data/src/alphabet/SymbolBase.h @@ -13,7 +13,9 @@ namespace alphabet { -typedef std::acceptor_base< +class SymbolBase; + +typedef std::acceptor_base<SymbolBase, LabeledSymbol, BlankSymbol, BottomOfTheStackSymbol, EndSymbol > VisitableSymbolBase; diff --git a/alib2data/src/automaton/AutomatonBase.h b/alib2data/src/automaton/AutomatonBase.h index 5442d018b1..ff3d4c3249 100644 --- a/alib2data/src/automaton/AutomatonBase.h +++ b/alib2data/src/automaton/AutomatonBase.h @@ -14,7 +14,9 @@ namespace automaton { -typedef std::acceptor_base< +class AutomatonBase; + +typedef std::acceptor_base<AutomatonBase, automaton::DFA, automaton::NFA, automaton::MultiInitialStateNFA, automaton::EpsilonNFA, automaton::CompactNFA, automaton::ExtendedNFA, automaton::DPDA, automaton::SinglePopDPDA, automaton::InputDrivenNPDA, automaton::VisiblyPushdownDPDA, automaton::VisiblyPushdownNPDA, automaton::RealTimeHeightDeterministicDPDA, automaton::RealTimeHeightDeterministicNPDA, automaton::NPDA, automaton::SinglePopNPDA, automaton::OneTapeDTM > VisitableAutomatonBase; diff --git a/alib2data/src/automaton/FSM/CompactNFA.h b/alib2data/src/automaton/FSM/CompactNFA.h index 97941daacb..5a8a23a227 100644 --- a/alib2data/src/automaton/FSM/CompactNFA.h +++ b/alib2data/src/automaton/FSM/CompactNFA.h @@ -13,6 +13,10 @@ #include "../common/SingleInitialState.h" #include "../common/InputAlphabet.h" #include "../../string/LinearString.h" +#include "EpsilonNFA.h" +#include "MultiInitialStateNFA.h" +#include "NFA.h" +#include "DFA.h" namespace automaton { diff --git a/alib2data/src/automaton/FSM/EpsilonNFA.h b/alib2data/src/automaton/FSM/EpsilonNFA.h index ad4f323aa8..348dead1da 100644 --- a/alib2data/src/automaton/FSM/EpsilonNFA.h +++ b/alib2data/src/automaton/FSM/EpsilonNFA.h @@ -15,6 +15,9 @@ #include "../common/InputAlphabet.h" #include "../../alphabet/Symbol.h" #include "../../string/Epsilon.h" +#include "MultiInitialStateNFA.h" +#include "NFA.h" +#include "DFA.h" namespace automaton { diff --git a/alib2data/src/automaton/FSM/ExtendedNFA.h b/alib2data/src/automaton/FSM/ExtendedNFA.h index 54db04aca6..6703e34da1 100644 --- a/alib2data/src/automaton/FSM/ExtendedNFA.h +++ b/alib2data/src/automaton/FSM/ExtendedNFA.h @@ -13,6 +13,11 @@ #include "../common/SingleInitialState.h" #include "../common/InputAlphabet.h" #include "../../regexp/RegExp.h" +#include "CompactNFA.h" +#include "EpsilonNFA.h" +#include "MultiInitialStateNFA.h" +#include "NFA.h" +#include "DFA.h" namespace automaton { diff --git a/alib2data/src/automaton/FSM/MultiInitialStateNFA.h b/alib2data/src/automaton/FSM/MultiInitialStateNFA.h index 830f166f36..e104ce8a51 100644 --- a/alib2data/src/automaton/FSM/MultiInitialStateNFA.h +++ b/alib2data/src/automaton/FSM/MultiInitialStateNFA.h @@ -14,6 +14,8 @@ #include "../common/MultiInitialStates.h" #include "../common/InputAlphabet.h" #include "../../alphabet/Symbol.h" +#include "NFA.h" +#include "DFA.h" namespace automaton { diff --git a/alib2data/src/automaton/FSM/NFA.cpp b/alib2data/src/automaton/FSM/NFA.cpp index f5ca944190..f92be7d733 100644 --- a/alib2data/src/automaton/FSM/NFA.cpp +++ b/alib2data/src/automaton/FSM/NFA.cpp @@ -6,7 +6,6 @@ */ #include "NFA.h" -#include "DFA.h" #include "../AutomatonException.h" #include <ostream> #include <sstream> diff --git a/alib2data/src/automaton/FSM/NFA.h b/alib2data/src/automaton/FSM/NFA.h index 24af23d31d..880ac3d3fd 100644 --- a/alib2data/src/automaton/FSM/NFA.h +++ b/alib2data/src/automaton/FSM/NFA.h @@ -15,6 +15,8 @@ #include "../common/InputAlphabet.h" #include "../../alphabet/Symbol.h" +#include "DFA.h" + namespace automaton { /** diff --git a/alib2data/src/container/ContainerBase.h b/alib2data/src/container/ContainerBase.h index c9eb75c43d..66c2ab8905 100644 --- a/alib2data/src/container/ContainerBase.h +++ b/alib2data/src/container/ContainerBase.h @@ -13,7 +13,9 @@ namespace container { -typedef std::acceptor_base< +class ContainerBase; + +typedef std::acceptor_base<ContainerBase, container::ObjectsSet, container::ObjectsVector, container::ObjectsPair, diff --git a/alib2data/src/grammar/GrammarBase.h b/alib2data/src/grammar/GrammarBase.h index 502ac204be..9ad26cb132 100644 --- a/alib2data/src/grammar/GrammarBase.h +++ b/alib2data/src/grammar/GrammarBase.h @@ -14,7 +14,9 @@ namespace grammar { -typedef std::acceptor_base< +class GrammarBase; + +typedef std::acceptor_base<GrammarBase, grammar::LeftLG, grammar::LeftRG, grammar::RightLG, grammar::RightRG, grammar::LG, grammar::CFG, grammar::EpsilonFreeCFG, grammar::CNF, grammar::GNF, grammar::CSG, grammar::NonContractingGrammar, grammar::ContextPreservingUnrestrictedGrammar, grammar::UnrestrictedGrammar > VisitableGrammarBase; diff --git a/alib2data/src/label/LabelBase.h b/alib2data/src/label/LabelBase.h index 58df68b672..1fea94675d 100644 --- a/alib2data/src/label/LabelBase.h +++ b/alib2data/src/label/LabelBase.h @@ -13,7 +13,9 @@ namespace label { -typedef std::acceptor_base< +class LabelBase; + +typedef std::acceptor_base<LabelBase, label::PrimitiveLabel, label::HexavigesimalLabel, label::ObjectLabel, label::LabelSetLabel, label::LabelPairLabel > VisitableLabelBase; diff --git a/alib2data/src/object/ObjectBase.h b/alib2data/src/object/ObjectBase.h index 87acf1f8b2..0a99bd83e8 100644 --- a/alib2data/src/object/ObjectBase.h +++ b/alib2data/src/object/ObjectBase.h @@ -115,7 +115,9 @@ class Character; namespace alib { -typedef std::acceptor_base< +class ObjectBase; + +typedef std::acceptor_base<ObjectBase, Void, exception::AlibException, automaton::DFA, automaton::NFA, automaton::MultiInitialStateNFA, automaton::EpsilonNFA, automaton::CompactNFA, automaton::ExtendedNFA, automaton::DPDA, automaton::SinglePopDPDA, automaton::InputDrivenNPDA, automaton::VisiblyPushdownDPDA, automaton::VisiblyPushdownNPDA, automaton::RealTimeHeightDeterministicDPDA, automaton::RealTimeHeightDeterministicNPDA, automaton::NPDA, automaton::SinglePopNPDA, automaton::OneTapeDTM, diff --git a/alib2data/src/primitive/PrimitiveBase.h b/alib2data/src/primitive/PrimitiveBase.h index 33866ca880..7a2dfe9a5f 100644 --- a/alib2data/src/primitive/PrimitiveBase.h +++ b/alib2data/src/primitive/PrimitiveBase.h @@ -13,7 +13,9 @@ namespace primitive { -typedef std::acceptor_base< +class PrimitiveBase; + +typedef std::acceptor_base<PrimitiveBase, primitive::String, primitive::Integer, primitive::Character > VisitablePrimitiveBase; diff --git a/alib2data/src/regexp/RegExpBase.h b/alib2data/src/regexp/RegExpBase.h index db3ae48d4f..639c6f52a7 100644 --- a/alib2data/src/regexp/RegExpBase.h +++ b/alib2data/src/regexp/RegExpBase.h @@ -13,7 +13,9 @@ namespace regexp { -typedef std::acceptor_base< +class RegExpBase; + +typedef std::acceptor_base<RegExpBase, UnboundedRegExp, FormalRegExp > VisitableRegExpBase; diff --git a/alib2data/src/regexp/formal/FormalRegExpElement.h b/alib2data/src/regexp/formal/FormalRegExpElement.h index ac25ee3184..e02d2d5382 100644 --- a/alib2data/src/regexp/formal/FormalRegExpElement.h +++ b/alib2data/src/regexp/formal/FormalRegExpElement.h @@ -25,11 +25,12 @@ class FormalRegExpEmpty; class FormalRegExpEpsilon; class UnboundedRegExpElement; +class FormalRegExpElement; /** * Abstract class representing element in the regular expression. Can be operator or symbol. */ -class FormalRegExpElement : public std::acceptor_base<FormalRegExpAlternation, FormalRegExpConcatenation, FormalRegExpIteration, FormalRegExpSymbol, FormalRegExpEmpty, FormalRegExpEpsilon> { +class FormalRegExpElement : public std::acceptor_base<FormalRegExpElement, FormalRegExpAlternation, FormalRegExpConcatenation, FormalRegExpIteration, FormalRegExpSymbol, FormalRegExpEmpty, FormalRegExpEpsilon> { protected: /* * Parent regexp contanining this instance of RegExpElement diff --git a/alib2data/src/regexp/unbounded/UnboundedRegExpElement.h b/alib2data/src/regexp/unbounded/UnboundedRegExpElement.h index c0ce6c8f9f..9d6ee37cec 100644 --- a/alib2data/src/regexp/unbounded/UnboundedRegExpElement.h +++ b/alib2data/src/regexp/unbounded/UnboundedRegExpElement.h @@ -25,11 +25,12 @@ class UnboundedRegExpEmpty; class UnboundedRegExpEpsilon; class FormalRegExpElement; +class UnboundedRegExpElement; /** * Abstract class representing element in the regular expression. Can be operator or symbol. */ -class UnboundedRegExpElement : public std::acceptor_base<UnboundedRegExpAlternation, UnboundedRegExpConcatenation, UnboundedRegExpIteration, UnboundedRegExpSymbol, UnboundedRegExpEmpty, UnboundedRegExpEpsilon> { +class UnboundedRegExpElement : public std::acceptor_base<UnboundedRegExpElement, UnboundedRegExpAlternation, UnboundedRegExpConcatenation, UnboundedRegExpIteration, UnboundedRegExpSymbol, UnboundedRegExpEmpty, UnboundedRegExpEpsilon> { protected: /** * Parent regexp contanining this instance of RegExpElement diff --git a/alib2data/src/std/visitor.hpp b/alib2data/src/std/visitor.hpp index e70671a1fc..d65eecdfa8 100644 --- a/alib2data/src/std/visitor.hpp +++ b/alib2data/src/std/visitor.hpp @@ -2,8 +2,8 @@ * Visitor.h * * Created on: Apr 05, 2014 - * Author: Andrew Durward - * Modified: Jan Travnicek + * Author: Andrew Durward + * Modified: Jan Travnicek */ #ifndef VISITOR_H_ @@ -21,17 +21,17 @@ class visitor; template<typename T> class visitor<T> { public: - virtual void Visit(void*, const T &) = 0; + virtual void Visit(void*, const T &) = 0; }; // specialization for multiple types template<typename T, typename... Types> class visitor<T, Types...> : public visitor<Types...> { public: - // promote the function(s) from the base class - using visitor<Types...>::Visit; + // promote the function(s) from the base class + using visitor<Types...>::Visit; - virtual void Visit(void*, const T &) = 0; + virtual void Visit(void*, const T &) = 0; }; // Visitor template declaration @@ -42,40 +42,126 @@ class const_visitor; template<typename T> class const_visitor<T> { public: - virtual void Visit(void*, const T &) const = 0; + virtual void Visit(void*, const T &) const = 0; }; // specialization for multiple types template<typename T, typename... Types> class const_visitor<T, Types...> : public const_visitor<Types...> { public: - // promote the function(s) from the base class - using const_visitor<Types...>::Visit; + // promote the function(s) from the base class + using const_visitor<Types...>::Visit; - virtual void Visit(void*, const T &) const = 0; + virtual void Visit(void*, const T &) const = 0; }; template<typename... Types> +class const_promoting_helper; + +template<typename Tested, typename... Other> +struct const_promoting_helper<Tested, Other...> { + + template<class Desired, class Base, class TargetVisitor, + typename std::enable_if< std::is_constructible<Desired, Tested>::value >::type* = nullptr > + inline static bool tryPromote(void* userData, const Desired& first, const Base& second, const TargetVisitor& visitor) { + if(dynamic_cast<const Tested*>(&second)) { + visitor.Visit(userData, first, Desired(dynamic_cast<const Tested&>(second))); + return true; + } else { + return const_promoting_helper<Other...>::tryPromote(userData, first, second, visitor); + } + } + + template<class Desired, class Base, class TargetVisitor, + typename std::enable_if< ! std::is_constructible<Desired, Tested>::value >::type* = nullptr > + inline static bool tryPromote(void* userData, const Desired& first, const Base& second, const TargetVisitor& visitor) { + return const_promoting_helper<Other...>::tryPromote(userData, first, second, visitor); + } +}; + +template<> struct const_promoting_helper<> { + template<class Desired, class Base, class TargetVisitor> + inline static bool tryPromote(void*, const Desired&, const Base&, const TargetVisitor&) { return false; } +}; + +// Visitor template declaration +template<typename... Types> +class const_promoting_visitor; + +// specialization for single type +template<typename T> +class const_promoting_visitor<T> { +public: + virtual void Visit(void*, const T &, const T&) const = 0; + + template<typename R, typename promoting_helper_type> + bool Visit1(void* userData, const T& first, const R& second) const { + return promoting_helper_type::tryPromote( userData, first, second, *this ); + } +}; + +// specialization for multiple types +template<typename T, typename... Types> +class const_promoting_visitor<T, Types...> : public const_promoting_visitor<Types...> { +public: + // promote the function(s) from the base class + using const_promoting_visitor<Types...>::Visit; + using const_promoting_visitor<Types...>::Visit1; + + virtual void Visit(void*, const T &, const T&) const = 0; + + template<typename R, typename promoting_helper_type> + bool Visit1(void* userData, const T& first, const R& second) const { + return promoting_helper_type::tryPromote( userData, first, second, *this ); + } +}; + +template<typename T, typename... Types> class acceptor_base { public: - typedef visitor<Types...> visitor_type; - typedef const_visitor<Types...> const_visitor_type; + typedef visitor<Types...> visitor_type; + + typedef const_visitor<Types...> const_visitor_type; - virtual void Accept(void* userData, visitor<Types...>& visitor) const = 0; - virtual void Accept(void* userData, const const_visitor<Types...>& visitor) const = 0; + typedef const_promoting_visitor<Types...> const_promoting_visitor_type; + typedef const_promoting_helper<Types...> const_promoting_helper_type; + typedef T base_type; + + virtual void Accept(void* userData, visitor<Types...>& visitor) const = 0; + + virtual void Accept(void* userData, const const_visitor<Types...>& visitor) const = 0; + + virtual bool Accept(void* userData, const T& other, const const_promoting_visitor<Types...>& visitor) const = 0; }; -template<typename Derived, typename Visitor, typename Base> +template<typename Derived, typename AcceptorBase, typename Base> class acceptor : public Base { public: - virtual void Accept(void* userData, typename Visitor::visitor_type& visitor) const { - visitor.Visit(userData, static_cast<const Derived&>(*this)); - } - virtual void Accept(void* userData, const typename Visitor::const_visitor_type& visitor) const { - visitor.Visit(userData, static_cast<const Derived&>(*this)); - } + virtual void Accept(void* userData, typename AcceptorBase::visitor_type& visitor) const { + visitor.Visit(userData, static_cast<const Derived&>(*this)); + } + virtual void Accept(void* userData, const typename AcceptorBase::const_visitor_type& visitor) const { + visitor.Visit(userData, static_cast<const Derived&>(*this)); + } + + virtual bool Accept(void* userData, const typename AcceptorBase::base_type& other, const typename AcceptorBase::const_promoting_visitor_type& visitor) const { + return visitor.template Visit1<typename AcceptorBase::base_type, typename AcceptorBase::const_promoting_helper_type>(userData, static_cast<const Derived&>(*this), other); + } }; + +template<class T, class R> +void Accept(void* userData, const T& first, const T& second, const R& visitor) { + bool res; + res = first.Accept(userData, second, visitor); + if(res) return; + + res = second.Accept(userData, first, visitor); + if(res) return; + + throw std::logic_error("cant promote parameters"); +} + } /* namespace std */ #endif /* VISITOR_H_ */ diff --git a/alib2data/src/string/StringBase.h b/alib2data/src/string/StringBase.h index 64ef5419e6..de7461bcde 100644 --- a/alib2data/src/string/StringBase.h +++ b/alib2data/src/string/StringBase.h @@ -13,7 +13,9 @@ namespace string { -typedef std::acceptor_base< +class StringBase; + +typedef std::acceptor_base<StringBase, string::Epsilon, string::LinearString, string::CyclicString > VisitableStringBase; @@ -27,7 +29,6 @@ public: virtual StringBase* clone() const = 0; virtual StringBase* plunder() && = 0; - }; } /* namespace string */ diff --git a/alib2data/test-src/std/StdVisitorTest.cpp b/alib2data/test-src/std/StdVisitorTest.cpp new file mode 100644 index 0000000000..314c3d0e13 --- /dev/null +++ b/alib2data/test-src/std/StdVisitorTest.cpp @@ -0,0 +1,233 @@ +#include "StdVisitorTest.h" +#include "std/visitor.hpp" +#include "common/base.hpp" +#include <set> +#include <string> + +CPPUNIT_TEST_SUITE_REGISTRATION( StdVisitorTest ); + +void StdVisitorTest::setUp() { +} + +void StdVisitorTest::tearDown() { +} + +class Tmp1; +class Tmp2; +class Tmp3; + +class TmpBase; + +typedef std::acceptor_base<TmpBase, + Tmp1, Tmp2, Tmp3 + > VisitableTmpBase; + +class TmpBase : + public alib::base< + TmpBase, + Tmp1, Tmp2, Tmp3 + >, public VisitableTmpBase { +}; + +class Tmp1 : public std::acceptor<Tmp1, VisitableTmpBase, TmpBase> { + int data; +public: + Tmp1(int data) : data(data) { + + } + + TmpBase* clone() const { + return new Tmp1(*this); + } + + TmpBase* plunder() && { + return new Tmp1(*this); + } + + virtual bool operator<(const TmpBase& other) const { + return other > *this; + } + + virtual bool operator==(const TmpBase& other) const { + return other == *this; + } + + virtual bool operator>(const TmpBase& other) const { + return other < *this; + } + + virtual bool operator==(const Tmp1& other) const { + return this->data == other.data; + } + + virtual bool operator<(const Tmp1& other) const { + return this->data < other.data; + } + + virtual void operator>>(std::ostream& os) const { + os << "Tmp1(" << data << ")"; + } + + virtual operator std::string() const { + return "Tmp1(" + std::to_string(data) + ")"; + } + + virtual int selfTypeId() const { + return typeId(*this); + } + + int getData() const { + return data; + } + +}; + +class Tmp2 : public std::acceptor<Tmp2, VisitableTmpBase, TmpBase> { + double data; +public: + Tmp2(double data) : data(data) { + + } + + Tmp2(const Tmp1& other) : data(other.getData()) { + + } + + TmpBase* clone() const { + return new Tmp2(*this); + } + + TmpBase* plunder() && { + return new Tmp2(*this); + } + + virtual bool operator<(const TmpBase& other) const { + return other > *this; + } + + virtual bool operator==(const TmpBase& other) const { + return other == *this; + } + + virtual bool operator>(const TmpBase& other) const { + return other < *this; + } + + virtual bool operator==(const Tmp2& other) const { + return this->data == other.data; + } + + virtual bool operator<(const Tmp2& other) const { + return this->data < other.data; + } + + virtual void operator>>(std::ostream& os) const { + os << "Tmp2(" << data << ")"; + } + + virtual operator std::string() const { + return "Tmp2(" + std::to_string(data) + ")"; + } + + virtual int selfTypeId() const { + return typeId(*this); + } + + double getData() const { + return data; + } + +}; + +class Tmp3 : public std::acceptor<Tmp3, VisitableTmpBase, TmpBase> { + std::string data; +public: + Tmp3(const std::string& data) : data(data) { + + } + + Tmp3(const Tmp1& other) : data(std::to_string(other.getData())) { + + } + + Tmp3(const Tmp2& other) : data(std::to_string(other.getData())) { + + } + + TmpBase* clone() const { + return new Tmp3(*this); + } + + TmpBase* plunder() && { + return new Tmp3(*this); + } + + virtual bool operator<(const TmpBase& other) const { + return other > *this; + } + + virtual bool operator==(const TmpBase& other) const { + return other == *this; + } + + virtual bool operator>(const TmpBase& other) const { + return other < *this; + } + + virtual bool operator==(const Tmp3& other) const { + return this->data == other.data; + } + + virtual bool operator<(const Tmp3& other) const { + return this->data < other.data; + } + + virtual void operator>>(std::ostream& os) const { + os << "Tmp3(" << data << ")"; + } + + virtual operator std::string() const { + return "Tmp3(" + data + ")"; + } + + virtual int selfTypeId() const { + return typeId(*this); + } + + const std::string& getData() const { + return data; + } + +}; + +class TmpVisitor : public VisitableTmpBase::const_promoting_visitor_type { + void Visit(void* userData, const Tmp1& first, const Tmp1& second) const { + int& data = *((int*) userData); + data = 1; + std::cout << first << " " << second << std::endl; + } + + void Visit(void* userData, const Tmp2& first, const Tmp2& second) const { + int& data = *((int*) userData); + data = 2; + std::cout << first << " " << second << std::endl; + } + + void Visit(void* userData, const Tmp3& first, const Tmp3& second) const { + int& data = *((int*) userData); + data = 3; + std::cout << first << " " << second << std::endl; + } +}; + +void StdVisitorTest::testPromoteVisitor() { + TmpVisitor visitor; + + Tmp1 tmp1(2); + Tmp3 tmp3("3"); + + int a = 0; + Accept((void*) &a, (TmpBase&) tmp1, (TmpBase&) tmp3, visitor); + + CPPUNIT_ASSERT(a == 3); +} diff --git a/alib2data/test-src/std/StdVisitorTest.h b/alib2data/test-src/std/StdVisitorTest.h new file mode 100644 index 0000000000..da75d57781 --- /dev/null +++ b/alib2data/test-src/std/StdVisitorTest.h @@ -0,0 +1,19 @@ +#ifndef VISITOR_TEST_H_ +#define VISITOR_TEST_H_ + +#include <cppunit/extensions/HelperMacros.h> + +class StdVisitorTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE( StdVisitorTest ); + CPPUNIT_TEST( testPromoteVisitor ); + CPPUNIT_TEST_SUITE_END(); + +public: + void setUp(); + void tearDown(); + + void testPromoteVisitor(); +}; + +#endif // VISITOR_TEST_H_ -- GitLab