More flexible any_cast for boost::any
Hello, I've been looking at ABIs and such (various unpleasant reasons). But I recently created the following code: #include <iostream> struct Base { virtual void check() = 0; template<typename T> T* IsDerivedFrom() { try { check(); } catch(T* p) { return p; } catch(...) { return nullptr; } return nullptr; } }; template<typename T> struct Derived : public Base { Derived(T obj) : t(obj) {} T t; void check() override final { throw &t; } }; struct A { virtual ~A() {} virtual void print() = 0;}; struct B : public A { int x; B(int y) : x(y) {} void print() override final { std::cout << x; } }; int main() { Base* b = new Derived<B>(B(5)); A* p = b->IsDerivedFrom<A>(); p->print(); } Whilst this is hardly the cleanest piece of code I've ever written, it also provides a base for implementing a more generic any_cast<ValueType>, which could succeed if ValueType is a base class of the stored type. Amazingly, the Standard requires the code to work but does not provide a cleaner means of implementation. I also note that, for some configurations, you could fall back to the Itanium ABI provided function directly, which would presumably be substantially faster and cleaner. Enabling this variety of any_cast would substantially improve the composability of boost::any. For example, it's arguable that std::function is merely boost::any but with additional interface requirements. With such an any_cast enhancement, it would be quite trivial to compose std::function implementations or similar concepts on top of boost::any.
2013/11/26 DeadMG
Hello,
I've been looking at ABIs and such (various unpleasant reasons). But I recently created the following code:
#include <iostream>
struct Base { virtual void check() = 0; template<typename T> T* IsDerivedFrom() { try { check(); } catch(T* p) { return p; } catch(...) { return nullptr; } return nullptr; } };
template<typename T> struct Derived : public Base { Derived(T obj) : t(obj) {} T t; void check() override final { throw &t; } };
struct A { virtual ~A() {} virtual void print() = 0;}; struct B : public A { int x; B(int y) : x(y) {} void print() override final { std::cout << x; } };
int main() { Base* b = new Derived<B>(B(5)); A* p = b->IsDerivedFrom<A>(); p->print(); }
Whilst this is hardly the cleanest piece of code I've ever written, it also provides a base for implementing a more generic any_cast<ValueType>, which could succeed if ValueType is a base class of the stored type. Amazingly, the Standard requires the code to work but does not provide a cleaner means of implementation.
This is a very interesting approach. But it has two drawbacks, because of exceptions usage: * it is slow * it won't work with exceptions disabled This can be implemented as a separate `polymorphic_any_cast` cast that is available only with exceptions on. In that way it won't affect performance of the existing any_casts and will improve usability. I'm not *the official* maintainer of the Boost.Any library, I'm just the one who made all the latest changes with rvalues and C++11 support. But if there'll be no objections and the official maintainer won't appear I can add this functionality to Boost.Any. -- Best regards, Antony Polukhin
I'd agree with implementing it separately, at least for now. Hopefully in
the future, the Standard will provide facilities for it. It shouldn't be
too difficult to put through Committee since it's already been demonstrated
that the feature must be implemented by all implementations today, even if
the existing characteristics of accessing it are very unfriendly.
But what I will note is that for some implementations, you can do a lot
better than this. For example, on Clang, you can use __has_include
toconditionally fall back to the Itanium ABI function
directly.https://svn.boost.org/trac/boost/ticket/6773 This
wouldn't require exceptions and would reduce the cost from throw/catch to
dynamic_cast, which is quite a bit more reasonable.
In any case, I merely wanted to make the maintainers of Boost.Any aware
that there is a generic implementation of such a polymorphic_any_cast, even
if it's not ideal. Then you can specialize for different implementations
and such.
On 27 November 2013 08:25, Antony Polukhin
2013/11/26 DeadMG
Hello,
I've been looking at ABIs and such (various unpleasant reasons). But I recently created the following code:
#include <iostream>
struct Base { virtual void check() = 0; template<typename T> T* IsDerivedFrom() { try { check(); } catch(T* p) { return p; } catch(...) { return nullptr; } return nullptr; } };
template<typename T> struct Derived : public Base { Derived(T obj) : t(obj) {} T t; void check() override final { throw &t; } };
struct A { virtual ~A() {} virtual void print() = 0;}; struct B : public A { int x; B(int y) : x(y) {} void print() override final { std::cout << x; } };
int main() { Base* b = new Derived<B>(B(5)); A* p = b->IsDerivedFrom<A>(); p->print(); }
Whilst this is hardly the cleanest piece of code I've ever written, it also provides a base for implementing a more generic any_cast<ValueType>, which could succeed if ValueType is a base class of the stored type. Amazingly, the Standard requires the code to work but does not provide a cleaner means of implementation.
This is a very interesting approach. But it has two drawbacks, because of exceptions usage: * it is slow * it won't work with exceptions disabled
This can be implemented as a separate `polymorphic_any_cast` cast that is available only with exceptions on. In that way it won't affect performance of the existing any_casts and will improve usability.
I'm not *the official* maintainer of the Boost.Any library, I'm just the one who made all the latest changes with rvalues and C++11 support. But if there'll be no objections and the official maintainer won't appear I can add this functionality to Boost.Any.
-- Best regards, Antony Polukhin
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Antony Polukhin wrote:
I'm not *the official* maintainer of the Boost.Any library, I'm just the one who made all the latest changes with rvalues and C++11 support. But if there'll be no objections and the official maintainer won't appear I can add this functionality to Boost.Any.
If I'm still the official maintainer I can happily pass my maintainership to Antony. PS do you know how type_erasure::any_cast handles this case? Alex
AMDG On 11/27/2013 12:52 PM, Alexander Nasonov wrote:
Antony Polukhin wrote:
I'm not *the official* maintainer of the Boost.Any library, I'm just the one who made all the latest changes with rvalues and C++11 support. But if there'll be no objections and the official maintainer won't appear I can add this functionality to Boost.Any.
If I'm still the official maintainer I can happily pass my maintainership to Antony.
PS do you know how type_erasure::any_cast handles this case?
It behaves exactly like boost::any_cast. In Christ, Steven Watanabe
2013/11/28 Alexander Nasonov
Antony Polukhin wrote:
I'm not *the official* maintainer of the Boost.Any library, I'm just the one who made all the latest changes with rvalues and C++11 support. But if there'll be no objections and the official maintainer won't appear I can add this functionality to Boost.Any.
If I'm still the official maintainer I can happily pass my maintainership to Antony.
Thanks! I'll do my best. -- Best regards, Antony Polukhin
At the moment, it's not possible to compose std::function on top of
boost::any because you can't get the interface back out of boost::any. But
with a polymorphic_any_cast, you can. Consider the following:
template<typename Signature> class function;
template
2013/11/28 Alexander Nasonov
I'm not *the official* maintainer of the Boost.Any library, I'm just
Antony Polukhin wrote: the
one who made all the latest changes with rvalues and C++11 support. But if there'll be no objections and the official maintainer won't appear I can add this functionality to Boost.Any.
If I'm still the official maintainer I can happily pass my maintainership to Antony.
Thanks! I'll do my best.
-- Best regards, Antony Polukhin
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
On 26 November 2013 09:24, DeadMG
Enabling this variety of any_cast would substantially improve the composability of boost::any. For example, it's arguable that std::function is merely boost::any but with additional interface requirements.
Well, they both use type erasure. I don't see how this exception trick helps, though.
With such an any_cast enhancement, it would be quite trivial to compose std::function implementations or similar concepts on top of boost::any.
Do you have a prototype implementation somewhere that we can look at? -- Nevin ":-)" Liber mailto:nevin@eviloverlord.com (847) 691-1404
participants (5)
-
Alexander Nasonov
-
Antony Polukhin
-
DeadMG
-
Nevin Liber
-
Steven Watanabe