Skip to content

Instantly share code, notes, and snippets.

@caiorss
Created June 10, 2020 03:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save caiorss/b153a0748519330dec0d153d2c608eb9 to your computer and use it in GitHub Desktop.
Save caiorss/b153a0748519330dec0d153d2c608eb9 to your computer and use it in GitHub Desktop.
Mapbox variant C++11,C++14 library review
#include <iostream>
#include <string>
#include <sstream>
#include <cassert>
#include <mapbox/variant.hpp>
namespace m = mapbox::util;
// Forward declarations
struct Add;
struct Mul;
using expr = m::variant<int, m::recursive_wrapper<Add>, m::recursive_wrapper<Mul>>;
struct Add
{
expr lhs;
expr rhs;
Add(expr lhs, expr rhs): lhs(lhs), rhs(rhs){ }
};
struct Mul
{
expr lhs;
expr rhs;
Mul(expr lhs, expr rhs): lhs(lhs), rhs(rhs){ }
};
struct EvalVisitor
{
int operator()(int x)
{
return x;
}
int operator()(Add const& v)
{
return m::apply_visitor(*this, v.lhs)
+ m::apply_visitor(*this, v.rhs);
}
int operator()(Mul const& v)
{
return m::apply_visitor(*this, v.lhs)
* m::apply_visitor(*this, v.rhs);
}
};
struct StringVisitor
{
std::string format_expr(expr node)
{
if(node.is<int>())
return std::to_string( node.get<int>() );
else
return std::string() + " (" + m::apply_visitor(*this, node) + ") ";
}
std::string operator()(int x)
{
return std::to_string(x);
}
std::string operator()(Add const& v)
{
return this->format_expr(v.rhs) + " + " + this->format_expr(v.lhs);
}
std::string operator()(Mul const& v)
{
return this->format_expr(v.rhs) + " * " + this->format_expr(v.lhs);
}
};
int main(int argc, char** argv)
{
std::cout << " [INFO] Running Ok " << std::endl;
std::cout << std::boolalpha;
// Abstract syntax tree
expr ast;
// Create visitor object
auto eval = EvalVisitor{};
auto disp = StringVisitor{};
ast = 10;
std::cout << " =>> is_num? = " << ast.is<int>() << "\n";
std::cout << " =>> value = " << ast.get<int>() << "\n";
std::cout << " =>> Expr 0 = " << m::apply_visitor(disp, ast) << "\n";
std::cout << " =>> Result 0 = " << m::apply_visitor(eval, ast) << '\n';
ast = Mul(5, Add(3, 4));
std::cout << "\n";
std::cout << " =>> is_num? = " << ast.is<int>() << "\n";
std::cout << " =>> is_add? = " << ast.is<Mul>() << "\n";
std::cout << " =>> Expr 1 = " << m::apply_visitor(disp, ast) << "\n";
std::cout << " =>> Result 1 = " << m::apply_visitor(eval, ast) << '\n';
// (10 + 4) * (5 * (3 + 8)) = 770
ast = Mul(Add(10, 4), Mul(5, Add(3, 8)));
std::cout << "\n";
std::cout << " =>> is_mul? = " << ast.is<Mul>() << "\n";
std::cout << " =>> Expr 2 = " << m::apply_visitor(disp, ast) << "\n";
int result = m::apply_visitor(eval, ast);
assert(result == 770);
std::cout << " =>> Result 2 = " << result << '\n';
return 0;
}
cmake_minimum_required(VERSION 3.9)
project(recursive-variant)
#========== Global Configurations =============#
#----------------------------------------------#
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# ------------ Download CPM CMake Script ----------------#
## Automatically donwload and use module CPM.cmake
file(DOWNLOAD https://raw.githubusercontent.com/TheLartians/CPM.cmake/v0.26.2/cmake/CPM.cmake
"${CMAKE_BINARY_DIR}/CPM.cmake")
include("${CMAKE_BINARY_DIR}/CPM.cmake")
#----------- Add dependencies --------------------------#
CPMAddPackage(
NAME mapbox-variant
URL https://github.com/mapbox/variant/archive/v1.1.6.zip
DOWNLOAD_ONLY YES
)
include_directories( ${mapbox-variant_SOURCE_DIR}/include )
message([TRACE] " mapbox source = ${mapbox-variant_SOURCE_DIR} ")
#----------- Set targets -------------------------------#
add_executable(app1 app1.cpp)
target_link_libraries(app1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment