yap/example/map_assign.cpp
Zach Laine a5ce500ef6 Add BOOST_YAP_USER_CALL_OPERATOR_N.
Partially addresses #51.
2018-03-03 20:27:13 -06:00

94 lines
2.9 KiB
C++

// Copyright (C) 2016-2018 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//[ map_assign
#include <boost/yap/algorithm.hpp>
#include <map>
#include <iostream>
// This transform applies all the call-subexpressions in a map_list_of
// expression (a nested chain of call operations) as a side effect; the
// expression returned by the transform is ignored.
template <typename Key, typename Value, typename Allocator>
struct map_list_of_transform
{
template <typename Fn, typename Key2, typename Value2>
auto operator() (boost::yap::expr_tag<boost::yap::expr_kind::call>,
Fn const & fn, Key2 && key, Value2 && value)
{
// Recurse into the function subexpression. Remember, transform()
// walks the nodes in an expression tree looking for matches. Once it
// finds a match, it is finished with that matching subtree. So
// without this recursive call, only the top-level call expression is
// matched by transform().
boost::yap::transform(
boost::yap::as_expr<boost::yap::minimal_expr>(fn), *this);
map.emplace(
std::forward<Key2 &&>(key),
std::forward<Value2 &&>(value)
);
// All we care about are the side effects of this transform, so we can
// return any old thing here.
return 0;
}
std::map<Key, Value, Allocator> & map;
};
// A custom expression template type for map_list_of expressions. We only
// need support for the call operator and an implicit conversion to a
// std::map.
template <boost::yap::expr_kind Kind, typename Tuple>
struct map_list_of_expr
{
static boost::yap::expr_kind const kind = Kind;
Tuple elements;
template <typename Key, typename Value, typename Allocator>
operator std::map<Key, Value, Allocator> () const
{
std::map<Key, Value, Allocator> retval;
map_list_of_transform<Key, Value, Allocator> transform{retval};
boost::yap::transform(*this, transform);
return retval;
}
BOOST_YAP_USER_CALL_OPERATOR_N(::map_list_of_expr, 2)
};
// A tag type for creating the map_list_of function terminal.
struct map_list_of_tag {};
auto map_list_of = boost::yap::make_terminal<map_list_of_expr>(map_list_of_tag{});
int main()
{
// Initialize a map:
std::map<std::string, int> op =
map_list_of
("<", 1)
("<=",2)
(">", 3)
(">=",4)
("=", 5)
("<>",6)
;
std::cout << "\"<\" --> " << op["<"] << std::endl;
std::cout << "\"<=\" --> " << op["<="] << std::endl;
std::cout << "\">\" --> " << op[">"] << std::endl;
std::cout << "\">=\" --> " << op[">="] << std::endl;
std::cout << "\"=\" --> " << op["="] << std::endl;
std::cout << "\"<>\" --> " << op["<>"] << std::endl;
return 0;
}
//]