/*
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:
/// boost::apply_visitor(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:
/// boost::apply_visitor(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:
/// boost::apply_visitor(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 {}; }
};
}