[Fusion] Output of adapted ADT

Hi,
I'm trying to output a string from an adapted class, but I'm getting
1>main.cpp(33): error C2679: binary '<<' : no operator found which
takes a right-hand operand of type
'boost::fusion::extension::adt_attribute_proxy

2011/4/8 Tore Halvorsen
Hi,
I'm trying to output a string from an adapted class, but I'm getting 1>main.cpp(33): error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'boost::fusion::extension::adt_attribute_proxy
' (or there is no acceptable conversion) for the following code (boost 1_46_1, msvc2010) Is there a header I'm missing? Very similar code works for BOOST_FUSION_DEFINE_STRUCT - and using ints or doubles also work...
In that case, boost::fusion::front returns not the real element, but a attribute_proxy that separates the use of getter & setter. Here's a workaround: std::cout << (std::string const&)boost::fusion::front(f) << std::endl;

On Fri, Apr 8, 2011 at 11:53 AM, TONGARI
I'm trying to output a string from an adapted class, but I'm getting 1>main.cpp(33): error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'boost::fusion::extension::adt_attribute_proxy
' (or there is no acceptable conversion) for the following code (boost 1_46_1, msvc2010) Is there a header I'm missing? Very similar code works for BOOST_FUSION_DEFINE_STRUCT - and using ints or doubles also work...
In that case, boost::fusion::front returns not the real element, but a attribute_proxy that separates the use of getter & setter.
Here's a workaround: std::cout << (std::string const&)boost::fusion::front(f) << std::endl;
Thanks, but I was not really looking for a workaround. My original problem was
actually trying to use an adapted ADT with spirit::karma, but thought I'd tackle
this seemingly simpler issue first.
(same as above)
foo f("foo");
using namespace boost::spirit::karma;
generate(std::ostream_iterator<char>(std::cout), string << eol, f);
... which fails with error C2039: 'const_iterator' : is not a member
of 'boost::fusion::extension::adt_attribute_proxy

On 4/8/2011 7:34 PM, Tore Halvorsen wrote:
On Fri, Apr 8, 2011 at 11:53 AM, TONGARI
wrote: I'm trying to output a string from an adapted class, but I'm getting 1>main.cpp(33): error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'boost::fusion::extension::adt_attribute_proxy
' (or there is no acceptable conversion) for the following code (boost 1_46_1, msvc2010) Is there a header I'm missing? Very similar code works for BOOST_FUSION_DEFINE_STRUCT - and using ints or doubles also work...
In that case, boost::fusion::front returns not the real element, but a attribute_proxy that separates the use of getter& setter.
Here's a workaround: std::cout<< (std::string const&)boost::fusion::front(f)<< std::endl;
Thanks, but I was not really looking for a workaround. My original problem was actually trying to use an adapted ADT with spirit::karma, but thought I'd tackle this seemingly simpler issue first.
(same as above)
foo f("foo"); using namespace boost::spirit::karma;
generate(std::ostream_iterator<char>(std::cout), string<< eol, f);
... which fails with error C2039: 'const_iterator' : is not a member of 'boost::fusion::extension::adt_attribute_proxy
' So, I guess that adapted_adts really can't be used in the same situations as adapted structs?
Adapted classes are different beasts. Adapted classes may not expose their attributes by reference due to abstraction and information hiding. It's not uncommon for a class not to actually have an actual member variable. The best we can assume is that a class has a getter and setter member functions. When you access its member (e.g. using at_c or dereferencing an iterator), here's what happens: 1) If the adapted class is immutable, it returns the class' adapted get member function for the member. E.g. T get_mem() const; 2) If the adapted class is mutable (your case), then it returns a proxy, that when assigned to, calls the class' adapted set member function for the member. E.g. void set_mem(T const&); The proxy also has a conversion to T which then returns the class' adapted get member function for the member. That's the best we can do. Regards, -- Joel de Guzman http://www.boostpro.com http://boost-spirit.com

2011/4/9 Joel de Guzman
Adapted classes are different beasts. Adapted classes may not expose their attributes by reference due to abstraction and information hiding. It's not uncommon for a class not to actually have an actual member variable. The best we can assume is that a class has a getter and setter member functions. When you access its member (e.g. using at_c or dereferencing an iterator), here's what happens:
1) If the adapted class is immutable, it returns the class' adapted get member function for the member.
E.g. T get_mem() const;
Really? Right after seeing your words I almost came up with a workaround... However, it turns out that it's either me misunderstanding you or it misbehaving. For example, const foo f("foo"); // immutable, right? boost::fusion::front(f); // we still get a proxy, why? 2) If the adapted class is mutable (your case), then it returns a
proxy, that when assigned to, calls the class' adapted set member function for the member.
E.g. void set_mem(T const&);
The proxy also has a conversion to T which then returns the class' adapted get member function for the member.
That's the best we can do.
Do you have any suggestion for using adapted class with Spirit that the OP wants to do? Thanks.

On 4/9/2011 3:39 PM, TONGARI wrote:
2011/4/9 Joel de Guzman
mailto:joel@boost-consulting.com> Adapted classes are different beasts. Adapted classes may not expose their attributes by reference due to abstraction and information hiding. It's not uncommon for a class not to actually have an actual member variable. The best we can assume is that a class has a getter and setter member functions. When you access its member (e.g. using at_c or dereferencing an iterator), here's what happens:
1) If the adapted class is immutable, it returns the class' adapted get member function for the member.
E.g. T get_mem() const;
Really? Right after seeing your words I almost came up with a workaround... However, it turns out that it's either me misunderstanding you or it misbehaving.
For example, const foo f("foo"); // immutable, right? boost::fusion::front(f); // we still get a proxy, why?
You'll have to forgive me. Christophe just pointed out off-list that this is no longer the behavior for the sake of consistency. Here's the relevant discussion: Stefan Strasser proposed changes to the adapt class/adt interface: ,---- [(http://lists.boost.org/Archives/boost/2010/08/169996.php)] |Also very good points. I think the proxy should behave similar to Boost |ref, as it should expose an implicit conversion to T. This alone will |satisfy many code that expects T. As for exposing the proxy as the |value type of the sequence, you are right. However, what we can |probably do is to be consistent with handling const and non-const and |always return a proxy so there is no surprise when code works one way |and not the other way. `---- Pardon the noise. I think the changes all make sense.
Do you have any suggestion for using adapted class with Spirit that the OP wants to do?
Well, given the current API, you can write: std::cout << boost::fusion::front(f).get() << std::endl; See: [http://tinyurl.com/6aq97lj] http://www.boost.org/doc/libs/1_46_1/libs/fusion/doc/html/fusion/notes.html#... Regards, -- Joel de Guzman http://www.boostpro.com http://boost-spirit.com

On Mon, Apr 11, 2011 at 1:53 AM, Joel de Guzman
On 4/9/2011 3:39 PM, TONGARI wrote:
Do you have any suggestion for using adapted class with Spirit that the OP wants to do?
Well, given the current API, you can write:
std::cout << boost::fusion::front(f).get() << std::endl;
Yeah, this works, but I'm still having trouble with karma.
I see that the documentation uses doubles and bools as an example
http://www.boost.org/doc/libs/1_46_1/libs/spirit/doc/html/spirit/karma/tutor...
... but I cannot get ints and strings to work. Am I missing something obvious?
template<typename T>
class sw // simple_wrapper
{
public:
sw(T tp) : t(tp) {}
T const& get() const { return t; }
void set(T const& tp) { t = tp; }
private:
T t;
};
BOOST_FUSION_ADAPT_TPL_ADT(
(T), (sw)(T),
(T const&, T const&, obj.get(), obj.set(val))
);
int main()
{
using namespace boost::spirit::karma;
// this works
sw<bool> const sw_bool(false);
generate(std::ostream_iterator<char>(std::cout), bool_ << eol, sw_bool);
// this works
sw<double> const sw_double(7.7);
generate(std::ostream_iterator<char>(std::cout), double_ << eol, sw_double);
// this fails with
// boost/spirit/home/karma/numeric/detail/numeric_utils.hpp(61):
error C2668: 'fabs' : ambiguous call to overloaded function
// VC\include\math.h(565): could be 'long double fabs(long double)'
// VC\include\math.h(517): or 'float fabs(float)'
// VC\include\math.h(118): or 'double fabs(double)' [found
using argument-dependent lookup]
// while trying to match the argument list
'(boost::fusion::extension::adt_attribute_proxy
participants (3)
-
Joel de Guzman
-
TONGARI
-
Tore Halvorsen