
Boost.variant provides visitation over an object whose types is within a certain set. To identify the type of the object, it uses an additional int that uniquely identifies the type of the object within the set. However, RTTI already provides unique identification for objects of polymorphic types within all types. I'm well aware that typeid(SomeType) is not a constant expression (which is quite a shame really, especially since I can't see any technical reason why it couldn't be) but it is still possible to do something like this: switch(typeid(o).name()[0]) { case 'F': switch(typeid(o).name()[1]) { case 'o': switch(typeid(o).name()[2]) { case 'o': switch(typeid(o).name()[3]) { case 0: // object of type "Foo" break; default: // unknown type } default: // unknown type } default: // unknown type } default: // unknown type } By providing the name of the types as a compile-time string, it could be possible to generate the implementation-specific mangled name and, from it, this kind of switch statement. This would allow O(1) (but with a possibly large constant) visitation of objects of polymorphic types non-intrusively. An utility could provide something like this: struct Base { virtual ~Base() = 0; }; struct Derived1 : Base { virtual Derived1() {} }; struct Derived2 : Base { virtual Derived2() {} }; struct Derived3 : Base { virtual Derived3() {} }; typedef mpl::map< mpl::pair< mpl::string<'D', 'e', 'r', 'i', 'v', 'e', 'd', '1'>, Derived1 >, mpl::pair< mpl::string<'D', 'e', 'r', 'i', 'v', 'e', 'd', '2'>, Derived2 >, mpl::pair< mpl::string<'D', 'e', 'r', 'i', 'v', 'e', 'd', '3'> Derived3 >
derived_types;
struct Visitor { typedef void result_type; template<typename T> void operator()(T&) const { // something useful } }; // b can actually be of any type derived from Base void foo(const Base& b) const { poly_visit<derived_types>(b, Visitor()); } Is there some interest in such a tool?

AMDG Mathias Gaunard wrote:
typedef mpl::map< mpl::pair< mpl::string<'D', 'e', 'r', 'i', 'v', 'e', 'd', '1'>, Derived1 >, mpl::pair< mpl::string<'D', 'e', 'r', 'i', 'v', 'e', 'd', '2'>, Derived2 >, mpl::pair< mpl::string<'D', 'e', 'r', 'i', 'v', 'e', 'd', '3'> Derived3 >
derived_types;
I think that you should associate the name with the types and then specify a list of types. template<> struct name_of<Derived1> : mpl::string<'D', 'e', 'r', 'i', 'v', 'e', 'd', '1'> {}; //... typedef mpl::vector<Derived1, Derived2, Derived3, ..., DerivedN> derived_types; Hmmm... This seems rather reminiscent of Typeof registration.
Is there some interest in such a tool?
Any chance that this could be generalized a bit to dispatching on a type_info object, so it can be used with any, too e.g.? struct Visitor { boost::any& any_; template<typename T> void operator()(wrap<T>) { T& t = boost::any_cast<T&>(any_); } }; In Christ, Steven Watanabe

On Fri, Mar 28, 2008 at 11:26 AM, Mathias Gaunard <mathias.gaunard@ens-lyon.org> wrote:
Boost.variant provides visitation over an object whose types is within a certain set. To identify the type of the object, it uses an additional int that uniquely identifies the type of the object within the set.
However, RTTI already provides unique identification for objects of polymorphic types within all types.
The typical use of a variant is to hold objects of types with value semantics. Most such types are not polymorphic and so dynamic RTTI can not be used to tell them apart. Could you provide more info about your specific use case? Could you use boost::any and dispatch based on RTTI? -- Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode

Very interesting. As far as use cases, one might take a look at extended_type_info in the serialization library. It seems related to this. Robert Ramey Emil Dotchevski wrote:
On Fri, Mar 28, 2008 at 11:26 AM, Mathias Gaunard <mathias.gaunard@ens-lyon.org> wrote:
Boost.variant provides visitation over an object whose types is within a certain set. To identify the type of the object, it uses an additional int that uniquely identifies the type of the object within the set.
However, RTTI already provides unique identification for objects of polymorphic types within all types.
The typical use of a variant is to hold objects of types with value semantics. Most such types are not polymorphic and so dynamic RTTI can not be used to tell them apart.
Could you provide more info about your specific use case? Could you use boost::any and dispatch based on RTTI?

On Fri, Mar 28, 2008 at 1:54 PM, Robert Ramey <ramey@rrsd.com> wrote:
Very interesting. As far as use cases, one might take a look at extended_type_info in the serialization library. It seems related to this.
I don't see a connection between boost::variant and extended_type_info. Isn't extended_type_info designed to handle any type? This is unlike boost::variant, which is just a type-safe union. -- Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode

Emil Dotchevski wrote:
On Fri, Mar 28, 2008 at 1:54 PM, Robert Ramey <ramey@rrsd.com> wrote:
Very interesting. As far as use cases, one might take a look at extended_type_info in the serialization library. It seems related to this.
I don't see a connection between boost::variant and extended_type_info. Isn't extended_type_info designed to handle any type? This is unlike boost::variant, which is just a type-safe union.
I agree. And, some simpler templating techniques may be used to map the current helt type discriminator to the (C++) type, thus dispatching calls by other means than what is typically referred to as 'visitation'. (I still fail to appreciate the usefulness of those compile-time static strings. I find them rather ugly...) Regards, Stefan -- ...ich hab' noch einen Koffer in Berlin...

Stefan Seefeld wrote:
I agree. And, some simpler templating techniques may be used to map the current helt type discriminator to the (C++) type, thus dispatching calls by other means than what is typically referred to as 'visitation'.
What techniques? There is certainly the Visitor design pattern, but that's intrusive and that doesn't provide generic visitation.
(I still fail to appreciate the usefulness of those compile-time static strings. I find them rather ugly...)
If you want to compute something on a string at compile-time, you need a compile-time string. Here, it is needed to mangle the possibles names at compile-time and build an automaton to recognize the mangled name RTTI provides. With a regular string, you would have to mangle the name at runtime, then do a linear search within the possible cases.

Mathias Gaunard wrote:
Stefan Seefeld wrote:
I agree. And, some simpler templating techniques may be used to map the current helt type discriminator to the (C++) type, thus dispatching calls by other means than what is typically referred to as 'visitation'.
What techniques?
As I understand your request, you want to roll your own switch statement, but with more expressive values than simple numbers. In other words, you want a mapping from types to variant type discriminators: variant<A, B, C> v = ....; switch (v.which()) { case v::type_id<A>::value: break; case v::type_id<B>::value: break; } (there are certainly many ways to spell that 'type_id' map above, I just made this up to illustrate my point.)
(I still fail to appreciate the usefulness of those compile-time static strings. I find them rather ugly...)
If you want to compute something on a string at compile-time, you need a compile-time string.
Certainly. But I haven't seen any good example on *what* I may want to compute on a string at compile-time. To me... struct my_compile_time_string; ...makes 'my_compile_time_string' a very lean and easy-to-read compile-time string. And as far as I know it's in use in boost in a lot of places already (not the least to generate intelligible compiler error messages, triggered during template instantiations). Regards, Stefan -- ...ich hab' noch einen Koffer in Berlin...

On Fri, Mar 28, 2008 at 3:21 PM, Stefan Seefeld <seefeld@sympatico.ca> wrote:
Mathias Gaunard wrote:
If you want to compute something on a string at compile-time, you need a compile-time string.
Certainly. But I haven't seen any good example on *what* I may want to compute on a string at compile-time.
We're going way OT with this but a good example is when you want to hard-code a hash value that is computed (at compile-time) from the (compile-time) string. -- Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode

Stefan Seefeld wrote:
As I understand your request, you want to roll your own switch statement, but with more expressive values than simple numbers. In other words, you want a mapping from types to variant type discriminators:
variant<A, B, C> v = ....; switch (v.which()) { case v::type_id<A>::value: break; case v::type_id<B>::value: break; }
It seems you completely misunderstood. I absolutely do not want to do such a thing. As I already said, what I want to do has no relation with variant. Variant is just an example of a library that does static visitation, and that uses its own type identification mechanism instead of the one bundled with C++. What I want to do, is to provide visitation on top of the native C++ RTTI feature, with "naked" and unmodified polymorphic variables (which are not in a variant or anything else that maintains its own additional type identifier). As the example I wrote demonstrated, as the title of the thread clearly states, etc. The switch was no example of interface: it was an example of how visitation could be *implemented*. Indeed, since RTTI is broken (it is not a constant expression), such tricks are necessary to make things work. The example of interface was after that. Basically, providing an variant-like interface for polymorphic objects that have already decayed.
Certainly. But I haven't seen any good example on *what* I may want to compute on a string at compile-time. To me...
This thread just provided one possible good reason to do so.

Emil Dotchevski wrote:
The typical use of a variant is to hold objects of types with value semantics. Most such types are not polymorphic and so dynamic RTTI can not be used to tell them apart.
Boost.variant was cited as an example of a system providing visitation. As in the describing code I wrote earlier, we are here talking of a free function, unrelated to variant. (Of course, variant could eventually try to use this to optimize some cases, memory usage-wise) The motivation is that very often, I've seen code that wanted to do different things based on the actual type of a polymorphic object, in certain cases at least. They either use quite a few dynamic_casts, which is inefficient, or use their own RTTI mechanism to do an ugly switch with downcasts. Or, if they really want to do different things in all cases, they use the heavyweight Visitor design pattern. I thought it was a shame to have to write your own RTTI system to do that. Due to the limitations of the standard RTTI system, though, it is required to do something a bit ugly and not as efficient as it could be, however. Maybe static visitation isn't much more concise and powerful than the visitation pattern, and thus not worth the hassle.
Could you provide more info about your specific use case? Could you use boost::any and dispatch based on RTTI?
Why not, the function could be extended to work with any polymorphic object or object which has a type_info& type() member function or free function.
participants (5)
-
Emil Dotchevski
-
Mathias Gaunard
-
Robert Ramey
-
Stefan Seefeld
-
Steven Watanabe