
Hi, I was playing with the any.hpp library trying to add a generic inserter to an ostrem. To acomplish that I created a pure virtual method print in the placeholder: class placeholder { ... virtual void print(std::ostream& out) const = 0; ... } implemented it in the template holder template<typename ValueType> class holder : public placeholder { ... virtual void print(std::ostream& out) const { out<<held; } ... }; and last but not least I implemented the inserter i the any class: class any { ... friend std::ostream& operator<<(std::ostream& out, const any& data) { data.content->print(out); return(out); }; ... }; this was my first attempt and I expected it to work fine, but to limit the use of any to classes that implement inserters, but I had a nice surprise to find out that as long I don´t actually invoke the inserter on non inserter implementing contained objects everything work fine, at least in bcc 5.5 and gcc(mingw) 3.4.2. when I do use the inserert operator for a nom implementing contained object I get a stack overflow exception, it seens like the inserter operator call the print method and print invoke the any inserter instead of the contained object inserter. Beeing able to strem out a unknow object is a huge plus in my current project and I thing it will be a great addition to the library, but I´m wondering how portable (standard compliant?) is my solution and why this recursive call happens with non inserter objects. Sorry if my explanation was not very clear or bad english, this is my first post in this mailing list and english is not my native language. just mail any need for clarifications. Sérgio

Sérgio Pace wrote:
Hi, I was playing with the any.hpp library trying to add a generic inserter to an ostrem. To acomplish that I created a pure virtual method print in the placeholder:
<snip code>
.. I had a nice surprise to find out that as long I donŽt actually invoke the inserter on non inserter implementing contained objects everything work fine, at least in bcc 5.5 and gcc(mingw) 3.4.2. when I do use the inserert operator for a nom implementing contained object I get a stack overflow exception ...
Your code looks fine, and works for me on VC7.1, gcc 3.4.1 (Cygwin) and Intel 8.0 for windows. Two comments, though: 1. Your code breaks boost::any for use with non-OutputStreamable types. You can fix this by dispatching on whether a type is output OutputStreamable, using the metafunction is_default_insertable, here: http://home.comcast.net/~jturkanis/format_lite/libs/format_lite/doc/?path=4.... 2. You should probably support narrow and wide streams.
Beeing able to strem out a unknow object is a huge plus in my current project and I thing it will be a great addition to the library, but IŽm wondering how portable (standard compliant?) is my solution and why this recursive call happens with non inserter objects.
I'm about to post an announcement for an interface library which can be thought of as a generalization of Boost.Any. Very roughly, while an instance of boost::any can be bound to any object (actually any instance of a value type), an interface reference can be bound to any object of a type which (non-intrusively) implements the interface. Although I haven't implemented operator overloading yet, use will be as follows: using namespace std; interface IStreamable { // pseudocode ostream& operator<<(ostream&); }; int main() { string s = "Hello World!\n"; IStreamable streamable = s; // std::string implements IStreamable cout << streamable; // prints "Hello World!\n"; } Here streamable is an "interface reference"; the library also contains "smart references" which, like interface reference, allow access to the bound object through the dot operator, but in addition manage the lifetime of the bound object, like boost::any.
Sérgio
Jonathan

Jonathan Turkanis wrote:
Sérgio Pace wrote:
Hi, I was playing with the any.hpp library trying to add a generic inserter to an ostrem. To acomplish that I created a pure virtual method print in the placeholder:
<snip code>
.. I had a nice surprise to find out that as long I don´t actually invoke the inserter on non inserter implementing contained objects everything work fine, at least in bcc 5.5 and gcc(mingw) 3.4.2. when I do use the inserert operator for a nom implementing contained object I get a stack overflow exception ...
Your code looks fine, and works for me on VC7.1, gcc 3.4.1 (Cygwin) and Intel 8.0 for windows.
Two comments, though:
1. Your code breaks boost::any for use with non-OutputStreamable types.
that´s the odd part it didn´t. as long I don´t use the insert operator i works fine and I don´t understant why it don´t break. see: class A {}; void foo() { A a; int b=0; any x; x = b; cout << x; b = any_cast<int>(x); x = a; // cout << x; // as long as this line is commented everything works fine a = any_cast<A>(x); } on the other hand if I do invoke the insert operator (<<) on a non-OutputStreamable type I get a stack overflow also I don´t understand why.
...You can fix this by dispatching on whether a type is output OutputStreamable, using the metafunction is_default_insertable, here:
great I was looking for some way of doing that. template metaprogramming rules! If I understood correctly you create a last choice overloaded operator<< that return tag and verify if check gets an ostrem or a tag is that correct?
2. You should probably support narrow and wide streams.
good idea
Beeing able to strem out a unknow object is a huge plus in my current project and I thing it will be a great addition to the library, but I´m wondering how portable (standard compliant?) is my solution and why this recursive call happens with non inserter objects.
I'm about to post an announcement for an interface library which can be thought of as a generalization of Boost.Any. Very roughly, while an instance of boost::any can be bound to any object (actually any instance of a value type), an interface reference can be bound to any object of a type which (non-intrusively) implements the interface. Although I haven't implemented operator overloading yet, use will be as follows:
I am following the "BIL" discussion for a while now, and I´m looking forward to put my hands on it
Sérgio
Jonathan

Sérgio Vale e Pace wrote:
Jonathan Turkanis wrote:
Two comments, though:
1. Your code breaks boost::any for use with non-OutputStreamable types.
that´s the odd part it didn´t. as long I don´t use the insert operator i works fine and I don´t understant why it don´t break. see:
class A {};
void foo() { A a; int b=0; any x; x = b; cout << x; b = any_cast<int>(x);
x = a; // cout << x; // as long as this line is commented everything works fine a = any_cast<A>(x); }
on the other hand if I do invoke the insert operator (<<) on a non-OutputStreamable type I get a stack overflow also I don´t understand why.
Anything is convertible to boost::any, and since you have an operator<< for boost::any, it will catch any object that doesn't have a better matched operator<< (i.e. any one that doesn't require a user defined conversion). If this didn't happen, you'd just get a compiler error when you tried to create an any<A>, since creation of that requires instantiation of all virtual functions of holder<A>, including the ill-formed print member (e.g. no overload matches the call out<<held). Dispatching to some kind of default call (which might just set failbit on the stream, or you could make it configurable) is probably the best way to handle this. Tom

Tom Widmer wrote:
Anything is convertible to boost::any, and since you have an operator<< for boost::any, it will catch any object that doesn't have a better matched operator<< (i.e. any one that doesn't require a user defined conversion). If this didn't happen, you'd just get a compiler error when you tried to create an any<A>, since creation of that requires instantiation of all virtual functions of holder<A>, including the ill-formed print member (e.g. no overload matches the call out<<held).
that explains it, thank's
Dispatching to some kind of default call (which might just set failbit on the stream, or you could make it configurable) is probably the best way to handle this.
could you elaborate on that, what do you mean by defaul call?
Tom
Sérgio

Sérgio Vale e Pace wrote:
Tom Widmer wrote:
Anything is convertible to boost::any, and since you have an operator<< for boost::any, it will catch any object that doesn't have a better matched operator<< (i.e. any one that doesn't require a user defined conversion). If this didn't happen, you'd just get a compiler error when you tried to create an any<A>, since creation of that requires instantiation of all virtual functions of holder<A>, including the ill-formed print member (e.g. no overload matches the call out<<held).
that explains it, thank's
Dispatching to some kind of default call (which might just set failbit on the stream, or you could make it configurable) is probably the best way to handle this.
could you elaborate on that, what do you mean by defaul call?
Every instantiation of holder will have to have a valid, compilable print member, since virtual functions are instantiated even if they aren't used. So, where a type isn't streamable, you need some kind of default behaviour for print just to get the code to compile. I suggested setting failbit on the stream, but you may prefer something else, or to make it configurable. Tom

thank´s On Thu, 27 Jan 2005 13:47:19 +0000, Tom Widmer <tom_usenet@hotmail.com> wrote:
Sérgio Vale e Pace wrote:
Tom Widmer wrote:
Anything is convertible to boost::any, and since you have an operator<< for boost::any, it will catch any object that doesn't have a better matched operator<< (i.e. any one that doesn't require a user defined conversion). If this didn't happen, you'd just get a compiler error when you tried to create an any<A>, since creation of that requires instantiation of all virtual functions of holder<A>, including the ill-formed print member (e.g. no overload matches the call out<<held).
that explains it, thank's
Dispatching to some kind of default call (which might just set failbit on the stream, or you could make it configurable) is probably the best way to handle this.
could you elaborate on that, what do you mean by defaul call?
Every instantiation of holder will have to have a valid, compilable print member, since virtual functions are instantiated even if they aren't used. So, where a type isn't streamable, you need some kind of default behaviour for print just to get the code to compile. I suggested setting failbit on the stream, but you may prefer something else, or to make it configurable.
Tom
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Sérgio Vale e Pace wrote:
Jonathan Turkanis wrote:
Sérgio Pace wrote:
great I was looking for some way of doing that. template metaprogramming rules!
It's not really template metaprogramming ... but I'm not really sure what to call it. I guess "Modern C++ Design" :-)
If I understood correctly you create a last choice overloaded operator<< that return tag and verify if check gets an ostrem or a tag is that correct?
I'd do it like this: #include < .... is_default_intertable.hpp> #include <boost/mpl/bool.hpp> template<typename ValueType> class holder : public placeholder { virtual void print(std::ostream& out) const { return print(out, is_default_insertable<ValueType>()); } void print(std::ostream& out, mpl::true_) { out<<held; } void print(std::ostream& out, mpl::false_) { // handle non-streamable types. For instance: out<< "boost::any[" << typeid(ValueType).name() << "]"; }
2. You should probably support narrow and wide streams.
good idea
I'm about to post an announcement for an interface library which can be thought of as a generalization of Boost.Any. Very roughly, while an instance of boost::any can be bound to any object (actually any instance of a value type), an interface reference can be bound to any object of a type which (non-intrusively) implements the interface. Although I haven't implemented operator overloading yet, use will be as follows:
I am following the "BIL" discussion for a while now, and IŽm looking forward to put my hands on it
Thanks. I'm surprised how many people have heard of it before I announced it here. Jonathan

S?rgio Pace wrote:
Hi, I was playing with the any.hpp library trying to add a generic inserter to an ostrem. To acomplish that I created a pure virtual method print in the placeholder: class placeholder { ... virtual void print(std::ostream& out) const = 0; ... } [...]
Have you look at dynamic_any? http://www.cuj.com/documents/s=8470/cujweb0309nasonov/ Unfortunately, it not yet "under review for inclusion with Boost" because I want to have multimethods there. I hope to get them in dynamic_any soon. -- Alexander Nasonov
participants (5)
-
Alexander Nasonov
-
Jonathan Turkanis
-
Sérgio Pace
-
Sérgio Vale e Pace
-
Tom Widmer