[log][phoenix] Bound arguments not protoified?

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

On Sat, Feb 2, 2013 at 8:26 PM, Andrey Semashev <andrey.semashev@gmail.com> wrote:
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).
Ping? Anyone? Should I create a ticket for Boost.Phoenix?

On 2/6/13 3:17 PM, Andrey Semashev wrote:
On Sat, Feb 2, 2013 at 8:26 PM, Andrey Semashev <andrey.semashev@gmail.com> wrote:
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).
Ping? Anyone? Should I create a ticket for Boost.Phoenix?
That would be best, yes. Seems Thomas Heller is very busy these days. I'll see if I can take over some of the support tasks. Regards, -- Joel de Guzman http://www.boostpro.com http://boost-spirit.com

On Wednesday 06 February 2013 22:31:50 Joel de Guzman wrote:
On 2/6/13 3:17 PM, Andrey Semashev wrote:
On Sat, Feb 2, 2013 at 8:26 PM, Andrey Semashev
<andrey.semashev@gmail.com> wrote:
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.
Ping? Anyone? Should I create a ticket for Boost.Phoenix?
That would be best, yes. Seems Thomas Heller is very busy these days. I'll see if I can take over some of the support tasks.
participants (2)
-
Andrey Semashev
-
Joel de Guzman