[spirit][karma+phoenix] Show result of member function

Hi,
How can karma be used to show the result of applying a member function to
objects in a container? Consider the following code (which does not compile)
to show the real and the imaginary parts of complex numbers stored in a
vector:
--8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<--
#include

On Sat, Apr 3, 2010 at 7:22 PM, Ravi
Hi, How can karma be used to show the result of applying a member function to objects in a container? Consider the following code (which does not compile) to show the real and the imaginary parts of complex numbers stored in a vector:
--8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<-- #include
#include #include #include #include <complex> #include <iostream> #include <vector>
namespace test {
template <typename Container> void show_container( const Container &ctr ) { typedef typename Container::value_type complex_t; typedef typename complex_t::value_type real_t; const real_t& ( complex_t::*real_func )() const = &complex_t::real; const real_t& ( complex_t::*imag_func )() const = &complex_t::imag;
namespace karma = boost::spirit::karma; namespace phoenix = boost::phoenix;
std::cout << karma::format( ( karma::double_[ // What goes here to extract the real part? karma::_1 = phoenix::bind( real_func, karma::_val ) ] << ',' << karma::double_[ karma::_1 = phoenix::bind( imag_func, karma::_val ) ] ) % karma::eol, ctr ); }
} // namespace test
int main( int, char *[] ) { std::vector< std::complex<double> > vec( 5 ); test::show_container( vec ); return 0; } --8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<--
The issue is that "karma::_1 = phoenix::bind( real_func, karma::_val )" seems unacceptable to the compiler (gcc 4.4.3, boost 1.42, Linux x86_64). The example above is a simplified version of much more complex code.
I would think that would work, but cannot test right now. You can always try to use the transform view in Fusion, that should work too, and execute slightly faster.

I'm traveling, so won't be able to get back on this before Tuesday. Regards Hartmut --------------- Meet me at BoostCon www.boostcon.com
-----Original Message----- From: boost-users-bounces@lists.boost.org [mailto:boost-users- bounces@lists.boost.org] On Behalf Of Ravi Sent: Saturday, April 03, 2010 8:22 PM To: boost-users@lists.boost.org Subject: [Boost-users] [spirit][karma+phoenix] Show result of member function
Hi, How can karma be used to show the result of applying a member function to objects in a container? Consider the following code (which does not compile) to show the real and the imaginary parts of complex numbers stored in a vector:
--8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<- - #include
#include #include #include #include <complex> #include <iostream> #include <vector>
namespace test {
template <typename Container> void show_container( const Container &ctr ) { typedef typename Container::value_type complex_t; typedef typename complex_t::value_type real_t; const real_t& ( complex_t::*real_func )() const = &complex_t::real; const real_t& ( complex_t::*imag_func )() const = &complex_t::imag;
namespace karma = boost::spirit::karma; namespace phoenix = boost::phoenix;
std::cout << karma::format( ( karma::double_[ // What goes here to extract the real part? karma::_1 = phoenix::bind( real_func, karma::_val ) ] << ',' << karma::double_[ karma::_1 = phoenix::bind( imag_func, karma::_val ) ] ) % karma::eol, ctr ); }
} // namespace test
int main( int, char *[] ) { std::vector< std::complex<double> > vec( 5 ); test::show_container( vec ); return 0; } --8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<- -
The issue is that "karma::_1 = phoenix::bind( real_func, karma::_val )" seems unacceptable to the compiler (gcc 4.4.3, boost 1.42, Linux x86_64). The example above is a simplified version of much more complex code.
Regards, Ravi
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

How can karma be used to show the result of applying a member function to objects in a container? Consider the following code (which does not compile) to show the real and the imaginary parts of complex numbers stored in a vector:
I added a new example (libs/spirit/example/karma/complex_number_adapt.cpp) demonstrating how to solve this by employing the new FUSION_ADAPT_CLASS macro. HTH Regards Hartmut --------------- Meet me at BoostCon www.boostcon.com

On Tuesday 06 April 2010 08:52:42 Hartmut Kaiser wrote:
How can karma be used to show the result of applying a member function to objects in a container? Consider the following code (which does not compile) to show the real and the imaginary parts of complex numbers stored in a vector:
I added a new example (libs/spirit/example/karma/complex_number_adapt.cpp) demonstrating how to solve this by employing the new FUSION_ADAPT_CLASS macro.
Thank you for the example. While this examples solves the specific problem of displaying complex numbers, it does not address my original question: how can phoenix be used with karma to assign the result of a member function to the attribute of a generator? For example, some complicated classes might have 20 member functions, each of which might be used with some specific grammar; in this case, the approach of using FUSION_ADAPT_CLASS would obscure the clarity of the grammar with a lot of "omit" directives. On other words, how would I replace the following so that it works for the complex number class? double_[ _1 = phoenix::bind( member_func, _val ) ] My understanding (and, apparently, OvermindDL1's as well) of phoenix and karma leads me to believe that the preceding should work. On a related note, the qi tutorial example for parsing into a struct does not show the simplest and, IMHO, the most maintainable way to fill up a struct that may evolve over time or simply has a lot of elements (such as a very application-specific config file parser): int_[ phoenix::bind( &employee::age, _val ) = _1 ] >> quoted_string[ phoenix::bind( &employee::forename, _val ) = _1 ] While the preceding may be inefficient due to use of semantic actions, it generalizes much better since it is essentially self-documenting (compared to at_c). FUSION_ADAPT_STRUCT is nice, but nowhere near as intuitive as above - all in my humble opinion, of course. Regards, Ravi

On Tuesday 06 April 2010 08:52:42 Hartmut Kaiser wrote:
How can karma be used to show the result of applying a member function to objects in a container? Consider the following code (which does not compile) to show the real and the imaginary parts of complex numbers stored in a vector:
I added a new example (libs/spirit/example/karma/complex_number_adapt.cpp) demonstrating how to solve this by employing the new FUSION_ADAPT_CLASS macro.
Thank you for the example. While this examples solves the specific problem of displaying complex numbers, it does not address my original question: how can phoenix be used with karma to assign the result of a member function to the attribute of a generator? For example, some complicated classes might have 20 member functions, each of which might be used with some specific grammar; in this case, the approach of using FUSION_ADAPT_CLASS would obscure the clarity of the grammar with a lot of "omit" directives.
On other words, how would I replace the following so that it works for the complex number class? double_[ _1 = phoenix::bind( member_func, _val ) ] My understanding (and, apparently, OvermindDL1's as well) of phoenix and karma leads me to believe that the preceding should work.
Sorry for not answering your question in the first place. The expression double_[ _1 = phoenix::bind( member_func, _val ) ] does work only if used in the rhs of a rule as _val refers to the rule's attribute (lhs attribute). Otherwise this looks fine to me.
On a related note, the qi tutorial example for parsing into a struct does not show the simplest and, IMHO, the most maintainable way to fill up a struct that may evolve over time or simply has a lot of elements (such as a very application-specific config file parser): int_[ phoenix::bind( &employee::age, _val ) = _1 ] >> quoted_string[ phoenix::bind( &employee::forename, _val ) = _1 ] While the preceding may be inefficient due to use of semantic actions, it generalizes much better since it is essentially self-documenting (compared to at_c).
Yes, that's purely personal taste. I personally prefer using the attribute propagation as it makes the grammar a lot less cluttered (and usually is faster at runtime).
FUSION_ADAPT_STRUCT is nice, but nowhere near as intuitive as above - all in my humble opinion, of course.
You don't necessarily need to utilize omit[]. Using the FUSION_ADAPT_[STRUCT|CLASS]_NAME variations allows to define several bindings for the same data structure, while exposing just the members you need. Regards Hartmut --------------- Meet me at BoostCon www.boostcon.com
participants (3)
-
Hartmut Kaiser
-
OvermindDL1
-
Ravi