Boost logo

Boost :

Subject: [boost] [log][phoenix] Bound arguments not protoified?
From: Andrey Semashev (andrey.semashev_at_[hidden])
Date: 2013-02-02 11:26:27


Hi,

I have a problem with Boost.Phoenix v3 bind implementation when used with
attribute keywords from Boost.Log. For some reason phoenix::bind does not
apply proto::detail::protoify to the bound arguments which breaks compilation
of some formatting expressions in Boost.Log.

Here's an example:

namespace logging = boost::log;
namespace expr = boost::log::expressions;
namespace phoenix = boost::phoenix;

// Custom severity level formatting function
std::string severity_level_as_urgency(
  logging::value_ref<
    logging::trivial::severity_level,
    logging::trivial::tag::severity > const& level);

// The function initializes the logging library
void init_logging()
{
  // ...
  sink->set_formatter
  (
    expr::stream
      << phoenix::bind(&severity_level_as_urgency, logging::trivial::severity)
  );
}

The intended behavior of this code is to invoke severity_level_as_urgency
function with severity level value extracted from a log record and put the
result of this function into a stream, thus forming a formatted representation
of the record.

trivial::severity is a keyword of type expr::attribute_keyword< ... >.
Keywords themselves should never actually be embedded into phoenix
expressions, instead I have attribute_actor that implements all the necessary
work to extract attribute values. I have specialized proto::detail::protoify
template for attribute_keyword (including references and reference_wrappers
thereof) so that it is automatically converted to attribute_actor whenever it
participates in expressions. But it doesn't work with the above code,
Boost.Phoenix embeds attribute_keyword as is into the expression. This results
in the error I posted in the end of the post.

I realize that proto::detail::protoify is not for public use and may not be
intended for my use case but I did not find any other way to implement what I
described. Anyway, I think bind should treat bound arguments as child
subexpressions and protoify them. Is that right?

In case if you want to see the complete code of the example and/or Boost.Log,
you can check it out from SVN:

svn co https://boost-log.svn.sourceforge.net/svnroot/boost-
log/branches/bleeding-edge boost-log

The example resides in libs/log/example/doc/extension_app_launcher.cpp. I have
modified it to call or_none() on trivial::severity so that the example
compiles; in order to reproduce the problem you have to remove this call (it
sould be performed by my protoify specialization instead).

Compilation error:

In file included from ./boost/phoenix/core/preprocessed/expression.hpp:12:0,
                 from ./boost/phoenix/core/expression.hpp:21,
                 from ./boost/phoenix/core/argument.hpp:14,
                 from ./boost/phoenix/core.hpp:17,
                 from ./boost/phoenix/phoenix.hpp:11,
                 from ./boost/phoenix.hpp:11,
                 from libs/log/example/doc/extension_app_launcher.cpp:13:
./boost/phoenix/core/preprocessed/expression_10.hpp: In instantiation of
‘static boost::phoenix::expr_ext<Actor, Tag, A0, A1>::type
boost::phoenix::expr_ext<Actor, Tag, A0, A1>::make(typename
boost::call_traits<A0>::param_type, typename
boost::call_traits<A1>::param_type) [with Actor = boost::phoenix::actor; Tag =
boost::phoenix::detail::tag::function_eval; A0 =
boost::phoenix::detail::function_ptr<1, std::basic_string<char>,
std::basic_string<char> (*)(const
boost::log::v2s_mt_posix::value_ref<boost::log::v2s_mt_posix::trivial::severity_level,
boost::log::v2s_mt_posix::trivial::tag::severity>&)>; A1 =
boost::log::v2s_mt_posix::expressions::attribute_keyword<boost::log::v2s_mt_posix::trivial::tag::severity>;
boost::phoenix::expr_ext<Actor, Tag, A0, A1>::type =
boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::detail::tag::function_eval,
boost::proto::argsns_::list2<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::phoenix::detail::function_ptr<1,
std::basic_string<char>, std::basic_string<char> (*)(const
boost::log::v2s_mt_posix::value_ref<boost::log::v2s_mt_posix::trivial::severity_level,
boost::log::v2s_mt_posix::trivial::tag::severity>&)> >, 0l>,
boost::log::v2s_mt_posix::expressions::attribute_actor<boost::log::v2s_mt_posix::trivial::severity_level,
boost::log::v2s_mt_posix::fallback_to_none,
boost::log::v2s_mt_posix::trivial::tag::severity, boost::phoenix::actor> >,
2l> >; typename boost::call_traits<A0>::param_type = const
boost::phoenix::detail::function_ptr<1, std::basic_string<char>,
std::basic_string<char> (*)(const
boost::log::v2s_mt_posix::value_ref<boost::log::v2s_mt_posix::trivial::severity_level,
boost::log::v2s_mt_posix::trivial::tag::severity>&)>&; typename
boost::call_traits<A1>::param_type = const
boost::log::v2s_mt_posix::expressions::attribute_keyword<boost::log::v2s_mt_posix::trivial::tag::severity>&]’:
./boost/phoenix/bind/bind_function.hpp:45:83: required from ‘const typename
boost::phoenix::detail::expression::function_eval<boost::phoenix::detail::function_ptr<1,
RT, RT (*)(T0)>, A0>::type boost::phoenix::bind(RT (*)(T0), const A0&) [with
RT = std::basic_string<char>; T0 = const
boost::log::v2s_mt_posix::value_ref<boost::log::v2s_mt_posix::trivial::severity_level,
boost::log::v2s_mt_posix::trivial::tag::severity>&; A0 =
boost::log::v2s_mt_posix::expressions::attribute_keyword<boost::log::v2s_mt_posix::trivial::tag::severity>;
typename
boost::phoenix::detail::expression::function_eval<boost::phoenix::detail::function_ptr<1,
RT, RT (*)(T0)>, A0>::type =
boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::detail::tag::function_eval,
boost::proto::argsns_::list2<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::phoenix::detail::function_ptr<1,
std::basic_string<char>, std::basic_string<char> (*)(const
boost::log::v2s_mt_posix::value_ref<boost::log::v2s_mt_posix::trivial::severity_level,
boost::log::v2s_mt_posix::trivial::tag::severity>&)> >, 0l>,
boost::log::v2s_mt_posix::expressions::attribute_actor<boost::log::v2s_mt_posix::trivial::severity_level,
boost::log::v2s_mt_posix::fallback_to_none,
boost::log::v2s_mt_posix::trivial::tag::severity, boost::phoenix::actor> >,
2l> >]’
libs/log/example/doc/extension_app_launcher.cpp:92:91: required from here
./boost/phoenix/core/preprocessed/expression_10.hpp:98:17: warning: missing
braces around initializer for
‘boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::detail::tag::function_eval,
boost::proto::argsns_::list2<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::phoenix::detail::function_ptr<1,
std::basic_string<char>, std::basic_string<char> (*)(const
boost::log::v2s_mt_posix::value_ref<boost::log::v2s_mt_posix::trivial::severity_level,
boost::log::v2s_mt_posix::trivial::tag::severity>&)> >, 0l>,
boost::log::v2s_mt_posix::expressions::attribute_actor<boost::log::v2s_mt_posix::trivial::severity_level,
boost::log::v2s_mt_posix::fallback_to_none,
boost::log::v2s_mt_posix::trivial::tag::severity, boost::phoenix::actor> >,
2l> >::expr_type {aka
boost::proto::exprns_::basic_expr<boost::phoenix::detail::tag::function_eval,
boost::proto::argsns_::list2<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::phoenix::detail::function_ptr<1,
std::basic_string<char>, std::basic_string<char> (*)(const
boost::log::v2s_mt_posix::value_ref<boost::log::v2s_mt_posix::trivial::severity_level,
boost::log::v2s_mt_posix::trivial::tag::severity>&)> >, 0l>,
boost::log::v2s_mt_posix::expressions::attribute_actor<boost::log::v2s_mt_posix::trivial::severity_level,
boost::log::v2s_mt_posix::fallback_to_none,
boost::log::v2s_mt_posix::trivial::tag::severity, boost::phoenix::actor> >,
2l>}’ [-Wmissing-braces]
./boost/phoenix/core/preprocessed/expression_10.hpp:98:17: warning: missing
braces around initializer for
‘boost::proto::exprns_::basic_expr<boost::phoenix::detail::tag::function_eval,
boost::proto::argsns_::list2<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::phoenix::detail::function_ptr<1,
std::basic_string<char>, std::basic_string<char> (*)(const
boost::log::v2s_mt_posix::value_ref<boost::log::v2s_mt_posix::trivial::severity_level,
boost::log::v2s_mt_posix::trivial::tag::severity>&)> >, 0l>,
boost::log::v2s_mt_posix::expressions::attribute_actor<boost::log::v2s_mt_posix::trivial::severity_level,
boost::log::v2s_mt_posix::fallback_to_none,
boost::log::v2s_mt_posix::trivial::tag::severity, boost::phoenix::actor> >,
2l>::proto_child0 {aka
boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::phoenix::detail::function_ptr<1,
std::basic_string<char>, std::basic_string<char> (*)(const
boost::log::v2s_mt_posix::value_ref<boost::log::v2s_mt_posix::trivial::severity_level,
boost::log::v2s_mt_posix::trivial::tag::severity>&)> >, 0l>}’ [-Wmissing-
braces]
./boost/phoenix/core/preprocessed/expression_10.hpp:98:17: error: could not
convert ‘boost::proto::make_expr<boost::phoenix::detail::tag::function_eval,
boost::proto::domainns_::basic_default_domain,
boost::phoenix::detail::function_ptr<1, std::basic_string<char>,
std::basic_string<char> (*)(const
boost::log::v2s_mt_posix::value_ref<boost::log::v2s_mt_posix::trivial::severity_level,
boost::log::v2s_mt_posix::trivial::tag::severity>&)>,
boost::log::v2s_mt_posix::expressions::attribute_keyword<boost::log::v2s_mt_posix::trivial::tag::severity>
>((* & a0), (* & a1))’ from ‘const type {aka const
boost::proto::exprns_::basic_expr<boost::phoenix::detail::tag::function_eval,
boost::proto::argsns_::list2<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::phoenix::detail::function_ptr<1,
std::basic_string<char>, std::basic_string<char> (*)(const
boost::log::v2s_mt_posix::value_ref<boost::log::v2s_mt_posix::trivial::severity_level,
boost::log::v2s_mt_posix::trivial::tag::severity>&)> >, 0l>,
boost::log::v2s_mt_posix::expressions::attribute_keyword<boost::log::v2s_mt_posix::trivial::tag::severity>
>, 2l>}’ to
‘boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::phoenix::detail::function_ptr<1,
std::basic_string<char>, std::basic_string<char> (*)(const
boost::log::v2s_mt_posix::value_ref<boost::log::v2s_mt_posix::trivial::severity_level,
boost::log::v2s_mt_posix::trivial::tag::severity>&)> >, 0l>::proto_child0 {aka
boost::phoenix::detail::function_ptr<1, std::basic_string<char>,
std::basic_string<char> (*)(const
boost::log::v2s_mt_posix::value_ref<boost::log::v2s_mt_posix::trivial::severity_level,
boost::log::v2s_mt_posix::trivial::tag::severity>&)>}’
./boost/phoenix/core/preprocessed/expression_10.hpp:98:17: error: no matching
function for call to
‘boost::log::v2s_mt_posix::expressions::attribute_actor<boost::log::v2s_mt_posix::trivial::severity_level,
boost::log::v2s_mt_posix::fallback_to_none,
boost::log::v2s_mt_posix::trivial::tag::severity,
boost::phoenix::actor>::attribute_actor(<brace-enclosed initializer list>)’
./boost/phoenix/core/preprocessed/expression_10.hpp:98:17: note: candidates
are:
In file included from ./boost/log/expressions.hpp:20:0,
                 from libs/log/example/doc/extension_app_launcher.cpp:16:
./boost/log/expressions/attr.hpp:174:14: note:
boost::log::v2s_mt_posix::expressions::attribute_actor<T, FallbackPolicyT,
TagT, ActorT>::attribute_actor(const base_type&) [with T =
boost::log::v2s_mt_posix::trivial::severity_level; FallbackPolicyT =
boost::log::v2s_mt_posix::fallback_to_none; TagT =
boost::log::v2s_mt_posix::trivial::tag::severity; ActorT =
boost::phoenix::actor;
boost::log::v2s_mt_posix::expressions::attribute_actor<T, FallbackPolicyT,
TagT, ActorT>::base_type =
boost::phoenix::actor<boost::log::v2s_mt_posix::expressions::attribute_terminal<boost::log::v2s_mt_posix::trivial::severity_level,
boost::log::v2s_mt_posix::fallback_to_none,
boost::log::v2s_mt_posix::trivial::tag::severity> >]
./boost/log/expressions/attr.hpp:174:14: note: candidate expects 1 argument,
0 provided
./boost/log/expressions/attr.hpp:156:7: note:
boost::log::v2s_mt_posix::expressions::attribute_actor<boost::log::v2s_mt_posix::trivial::severity_level,
boost::log::v2s_mt_posix::fallback_to_none,
boost::log::v2s_mt_posix::trivial::tag::severity,
boost::phoenix::actor>::attribute_actor(const
boost::log::v2s_mt_posix::expressions::attribute_actor<boost::log::v2s_mt_posix::trivial::severity_level,
boost::log::v2s_mt_posix::fallback_to_none,
boost::log::v2s_mt_posix::trivial::tag::severity, boost::phoenix::actor>&)
./boost/log/expressions/attr.hpp:156:7: note: candidate expects 1 argument,
0 provided


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk