diff --git a/alib2data/src/alphabet/SymbolBase.h b/alib2data/src/alphabet/SymbolBase.h
index ce062e65ae78abf67d4dc4604bb850c0647d02a9..18027e6451d69f9f2e1fcfb60010a0aee86982a4 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 5442d018b1a6566e79fae079c0d9549e9c06b960..ff3d4c3249d4d49edf9efd8b5ed16a1272709fc8 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 97941daacb196266c8a23b27b8ad146bb92fc0e8..5a8a23a227ac9bb370fa698764ecfac52ba92942 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 ad4f323aa83271fd14e3a827e1c43a9d819d08ea..348dead1da57cbe7a44441127aebdbdff85d2975 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 54db04aca6e5bec7d587b73bb44ac17dfbd873ff..6703e34da19ac305a35047a9222c76f68960b4aa 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 830f166f3645ebbecc253bd0a6662dccd00bb43b..e104ce8a511c725dd6096108c88c2dbf0949b7c6 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 f5ca944190775e3fd11b485b8c9b3c57782567c0..f92be7d733b9e850a894a0091be3c0bd37164ba9 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 24af23d31d5ef6e50b9c9a41c5edef67c169edc6..880ac3d3fda4c80eac8c2df81ade7f438dc6a3cb 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 c9eb75c43d47ca37c466162ab1e515a571e60912..66c2ab8905f9a30ff2aa11bc8aae3197ee607b11 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 502ac204be4bb18e9288cda7073a356ec8782eca..9ad26cb132a22477edd1c2dfb9d6c146baa246b8 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 58df68b6728c00e3f109d3b7a51194b67ce88938..1fea94675d052263aa48215a5935623e21cce3ec 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 87acf1f8b27163e061116bdf9159e32485435d6b..0a99bd83e8ccc3a30a4869c895e515ecb6749650 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 33866ca880fb1a088cbc3e7c17c50b494379e889..7a2dfe9a5fc640df7bce67e3edd4fa1cb7864f68 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 db3ae48d4f0ff45ab4641c96e3c62c4d6facc4ed..639c6f52a703e6e2fff69b5afd8ea3a36b2da3aa 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 ac25ee31840c6a913e4823548b281feeccd8fd2f..e02d2d5382d34ad67c6a5c2828c9696326256b05 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 c0ce6c8f9f13d32f1a31f3de3d8f1bf68967c6bb..9d6ee37cec27443f46a389efb3d827a8a6ac96e6 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 e70671a1fc2fac16064feca4a5ba84503852cd53..d65eecdfa82fa22f394bfb35f8bb092fe1fcb9e6 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 64ef5419e6d3b03b6cfe014901241ac784d9157f..de7461bcde6a07e06b4d00002de01830cc9b768a 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 0000000000000000000000000000000000000000..314c3d0e13da0856f2aa2423a11e3708872bcaf0
--- /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 0000000000000000000000000000000000000000..da75d57781b8b15d9c95415052ec1b8d8db022ab
--- /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_