/* This file is part of solidity. solidity is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. solidity is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with solidity. If not, see . */ /** * Visitor templates. */ #pragma once #include #include namespace dev { /// Generic visitor used as follows: /// std::visit(GenericVisitor( /// [](Class1& _c) { _c.f(); }, /// [](Class2& _c) { _c.g(); } /// ), variant); /// This one does not have a fallback and will fail at /// compile-time if you do not specify all variants. template struct GenericVisitor{}; template struct GenericVisitor: public GenericVisitor { using GenericVisitor::operator (); explicit GenericVisitor( std::function _visitor, std::function... _otherVisitors ): GenericVisitor(std::move(_otherVisitors)...), m_visitor(std::move(_visitor)) {} void operator()(Visitable& _v) const { m_visitor(_v); } std::function m_visitor; }; template <> struct GenericVisitor<>: public boost::static_visitor<> { void operator()() const {} }; /// Generic visitor with fallback: /// std::visit(GenericFallbackVisitor( /// [](Class1& _c) { _c.f(); }, /// [](Class2& _c) { _c.g(); } /// ), variant); /// This one DOES have a fallback and will NOT fail at /// compile-time if you do not specify all variants. template struct GenericFallbackVisitor{}; template struct GenericFallbackVisitor: public GenericFallbackVisitor { explicit GenericFallbackVisitor( std::function _visitor, std::function... _otherVisitors ): GenericFallbackVisitor(std::move(_otherVisitors)...), m_visitor(std::move(_visitor)) {} using GenericFallbackVisitor::operator (); void operator()(Visitable& _v) const { m_visitor(_v); } std::function m_visitor; }; template <> struct GenericFallbackVisitor<>: public boost::static_visitor<> { template void operator()(T&) const { } }; /// Generic visitor with fallback that can return a value: /// std::visit(GenericFallbackReturnsVisitor( /// [](Class1& _c) { return _c.f(); }, /// [](Class2& _c) { return _c.g(); } /// ), variant); /// This one DOES have a fallback and will NOT fail at /// compile-time if you do not specify all variants. /// The fallback {}-constructs the return value. template struct GenericFallbackReturnsVisitor{}; template struct GenericFallbackReturnsVisitor: public GenericFallbackReturnsVisitor { explicit GenericFallbackReturnsVisitor( std::function _visitor, std::function... _otherVisitors ): GenericFallbackReturnsVisitor(std::move(_otherVisitors)...), m_visitor(std::move(_visitor)) {} using GenericFallbackReturnsVisitor::operator (); R operator()(Visitable& _v) const { return m_visitor(_v); } std::function m_visitor; }; template struct GenericFallbackReturnsVisitor: public boost::static_visitor { template R operator()(T&) const { return {}; } }; }