Boost logo

Boost :

Subject: Re: [boost] [log][phoenix] Questions on porting to phoenix
From: Andrey Semashev (andrey.semashev_at_[hidden])
Date: 2012-01-24 01:41:54


On Mon, Jan 23, 2012 at 5:07 PM, Thomas Heller
<thom.heller_at_[hidden]> wrote:
> On Mon, Jan 23, 2012 at 1:57 PM, Andrey Semashev
> <andrey.semashev_at_[hidden]> wrote:
>> On Mon, Jan 23, 2012 at 2:37 PM, TONGARI <tongari95_at_[hidden]> wrote:
>>>
>>> I wrote the sample code that conforms these requirements, full code
>>> attached.
>>
>> Thanks a lot, this will greatly help me to get started.
>>
>> So, as I understand, the env argument to the actor contains arguments
>> provided for evaluation. In case of filtering expression, this is fine
>> as there is only one argument - the set of attributes. But in case of
>> formatter there are two arguments - the stream and the log record.
>> Does Phoenix pass both arguments to the actor in this case?
>
> Yes, the environment is a fusion tuple.

Ok, so it seems the attribute actor will have to be an unary function
and always expect either a log record or a set of attribute values as
the first argument. It's fine, as long as the argument can be rebound
with phoenix::bind.

A few more questions, if I may.

1. I would like to cache some data in the actor at the point of AST
construction. For instance, I'd like to cache the attribute name (in
the actual code it's not really a string but rather an adapter
constructible from a string; I'd like to avoid its construction at the
expression evaluation time) and, possibly, a default value for the
attribute. Is this possible? The attribute keyword should still be a
POD (or at least, be safely constructible at the namespace scope), so
the cached data can only be provided only by a function call.

2. I would like the keyword have additional methods, in particular,
for default attribute value provision. Extending my initial syntax,
this would be:

  BOOST_LOG_REGISTER_ATTRIBUTE("Severity", severity, my_severity)

  attribute_values_view attrs;

  severity(attrs); // returns optional<my_severity>
  severity.or_default(info)(attrs); // returns my_severity, which is
info by default

As I understand, the only way I can do that, except for reimplementing
phoenix::actor, is to derive my actor from phoenix::actor. This makes
the attribute keyword non-POD in C++03 but is it still safe to be
constructed in the namespace scope, provided that the keyword does not
have its own data members? Also, what should be the template argument
for the phoenix::actor specialization? Here's the code example to
illustrate what I'm talking about:

  template< typename DescriptorT >
  struct attribute_keyword :
    public phoenix::actor< what_should_be_here? >
  {
    // extracts the attribute value
    template< typename ContextT >
    DescriptorT::value_type operator() (ContextT const& ctx) const;

    // adds a default value
    attribute_keyword_with_default< DescriptorT >
    or_default(DescriptorT::value_type) const;
  };

  // assume there are specializations of custom_terminal and
  // is_custom_terminal for attribute_keyword

  // This is generated by BOOST_LOG_REGISTER_ATTRIBUTE
  namespace tag {
  struct severity
  {
    typedef my_severity value_type;
    typedef attribute_name name_type;

    // returns an equivalent for "Severity"
    // I want to cache its result in the AST
    static name_type get_name();
  };
  }
  const attribute_keyword< tag::severity > severity; // is this safe?

> I have to admit the docs are very unclear about that specifc part ...
> needs some loving.

Right, the docs are lacking a good tutorial for library extenders. Its
internals are rather complicated to gather this information from.


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