[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<foo,0,false>' (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... #include <iostream> #include <string> #include <ostream> #include <boost/fusion/include/adapted.hpp> #include <boost/fusion/sequence.hpp> class foo { public: foo(std::string const& str) : s(str) { } std::string const& get_s() const { return s; } void set_s(std::string const& str) { s = str; } private: std::string s; }; BOOST_FUSION_ADAPT_ADT( foo, (std::string const&, std::string const&, obj.get_s(), obj.set_s(val)) ); int main(int argc, char* argv[]) { foo f("foo"); std::cout << boost::fusion::front(f) << std::endl; return EXIT_SUCCESS; } -- Eld på åren og sol på eng gjer mannen fegen og fjåg. [Jøtul] <demo> 2011 Tore Halvorsen || +052 0553034554
2011/4/8 Tore Halvorsen <tore.halvorsen@gmail.com>
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<foo,0,false>' (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 <tongari95@gmail.com> 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<foo,0,false>' (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<foo,0,true>' So, I guess that adapted_adts really can't be used in the same situations as adapted structs? -- Eld på åren og sol på eng gjer mannen fegen og fjåg. [Jøtul] <demo> 2011 Tore Halvorsen || +052 0553034554
On 4/8/2011 7:34 PM, Tore Halvorsen wrote:
On Fri, Apr 8, 2011 at 11:53 AM, TONGARI<tongari95@gmail.com> 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<foo,0,false>' (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<foo,0,true>'
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 <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? 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 <joel@boost-consulting.com <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 <joel@boost-consulting.com> wrote:
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<T,N,Const>)' sw<int> const sw_int(7); generate(std::ostream_iterator<char>(std::cout), int_ << eol, sw_int); // this fails with // boost/spirit/home/support/container.hpp(174): error C2039: 'const_iterator' // : is not a member of 'boost::fusion::extension::adt_attribute_proxy<T,N,Const>' // with[T=sw<std::string>,N=0,Const=true] sw<std::string> const sw_string("foo"); generate(std::ostream_iterator<char>(std::cout), string << eol, sw_string); } -- Eld på åren og sol på eng gjer mannen fegen og fjåg. [Jøtul] <demo> 2011 Tore Halvorsen || +052 0553034554
participants (3)
-
Joel de Guzman
-
TONGARI
-
Tore Halvorsen