metaprogramming: associating a type with another type

hi boosters while solving my own design problems i accidentally discovered an interesting technique let's assume we want to associate some value (a type) to a newly created type so we can easily access the associated type during metaprogramming let's call the associated type a property then we have the following property types: struct property0 {}; struct property1 {}; struct property2 {}; now we want to access the associated property for an arbitrary type in a natural traits manner: property<arbitrary_type>::type it appears we can implement it almost trivially (if know how) (let's assume we have portable typeof() facility) consider the code //the return type of this function appears to be the default property template<typename type> property0 get_prop(type*); //do not implement! template<typename t> struct property { typedef typeof(get_prop((type*)42) type; }; template<typename type, typename p = typename property<type>::type> struct base { friend p get_prop(type*) { return p(); } }; template<typename type> void foo(const base<type>&) //handles ALL types derived from base { typedef typename property<type>::type associated_property; } template<typename type> void bar(const base<type, property2>&) //handles ONLY types with property2 {} struct s : public expression<s> //default property used here {}; struct s1 : public expression<s1, property1> {}; struct s2 : public expression<s2, property2> {}; int main() { foo(s()); foo(s1()); foo(s2()); //bar(s()); //should not compile //bar(s1()); //should not compile bar(s2()); return 0; } even with the lack of typeof(), given a fixed set of properties it is very easy to implement this technique see working example at http://codepad.org/qXkESprl personally i see it as extremely useful for generic lib writers for some designes (of course if appropriately applied) as well as for users of such libs i would appreciate any thoughts on improvement of this technique within C++98 standard also any thoughts on portability are welcome if you have questions about how and/or why does it work feel free to ask -- Pavel

DE wrote:
hi boosters while solving my own design problems i accidentally discovered an interesting technique ... template<typename t> struct property { typedef typeof(get_prop((type*)42) type; };
This here makes no sense. The property template does not depend on t and the typedef is cyclicly defined. I'm guessing you intended: template<typename t> struct property { typedef typeof(get_prop((t*)42) type; }; But even so I don't quite understand what you're driving at because you never use the property template in your example. It the point that you never have to specialize traits for the property type of a class that derives from base? Isn't deriving from base a stronger requirement than the specialization of a metafunction? I'm also confused by this:
template<typename type, typename p = typename property<type>::type> struct base { friend p get_prop(type*) { return p(); } };
property<type>::type will always return property0. Is your intention that people fully specialize property<> for their type to override the default behavior, or to specialize get_prop<>? Since I'm not sure what your goal is I can't say there is anything wrong with your design, but it seems to me that there are elements of your design that serve no obvious function. Perhaps you can provide a larger example to make the benefit of your approach clearer to those of us who haven't finished our morning coffee yet. Thanks, Luke

i'm very glad you are asking on 29.01.2010 at 21:12 Simonson, Lucanus J wrote :
This here makes no sense. The property template does not depend on t and the typedef is cyclicly defined. I'm guessing you intended:
template<typename t> struct property { typedef typeof(get_prop((t*)42) type; }; yes you are write here, it's a typo the source at codepad seems to be typo-free
But even so I don't quite understand what you're driving at because you never use the property template in your example. i use it to define default template parameter in the 'base' declaration
Is the point that you never have to specialize traits for the property type of a class that derives from base? yep
Isn't deriving from base a stronger requirement than the specialization of a metafunction? indeed this technique is intended for such systems, not for traits driven ones
I'm also confused by this:
template<typename type, typename p = typename property<type>::type> struct base { friend p get_prop(type*) { return p(); } };
property<type>::type will always return property0. Is your intention that people fully specialize property<> for their type to override the default behavior, or to specialize get_prop<>? ideally user will not ever touch property<> class here is the interesting part comes into play when you define a type deriving from base<my_type, propertyX> an appropriate function is introduced (as a friend), namely propertyX get_prop(my_typ*) {/*...*/} but when a type deriving base<my_type> is defined the second template argument computed automatically as property<type>::type but since the needed function is not yet introduced it is defined as the default value (property0 in the example)
Since I'm not sure what your goal is I can't say there is anything wrong with your design, but it seems to me that there are elements of your design that serve no obvious function. Perhaps you can provide a larger example to make the benefit of your approach clearer to those of us who haven't finished our morning coffee yet. my goal is to ease definition of template functions and metaprogramming particularly the ability to define expressions (in an expression templates based lib) in the form
struct s : public base<s> {}; or struct X : public base<s, propertyX> {}; and be able to write template functions which handle either all of the types derived from base or types associated with a specific property template<typename type1, typename type2> int foo(const base<type1>&, const base<type2>&) {//handles ANY two types derived from base with arbitrary properties } template<typename type1, typename type2> int foo(const base<type1>&, const base<type2, propertyX>&) {//the first argument can be ANY type but the second must be associated with propertyX } that is s object; X x; foo(s, s); //compiles foo(s, x); //compiles foo(x, x); //compiles bar(s, x); //compiles bar(x, s); //does not compile bar(x, x); //does not compile -- Pavel

template<typename type1, typename type2> int foo(const base<type1>&, const base<type2>&) {//handles ANY two types derived from base with arbitrary properties }
template<typename type1, typename type2> int foo(const base<type1>&, const base<type2, propertyX>&) {//the first argument can be ANY type but the second must be associated with propertyX }
the latter must be bar() of course -- Pavel

Ain't you reinventing tag-disptaching based on type-traits but just with a cumbersome system ? -- ___________________________________________ Joel Falcou - Assistant Professor PARALL Team - LRI - Universite Paris Sud XI Tel : (+33)1 69 15 66 35

DE wrote:
anyway i think the appearing of one new (?) technique won't hurt anyone
I see what you did there ;) Need to be polished a bit I think. -- ___________________________________________ Joel Falcou - Assistant Professor PARALL Team - LRI - Universite Paris Sud XI Tel : (+33)1 69 15 66 35

on 30.01.2010 at 9:55 joel falcou wrote :
I see what you did there ;) Need to be polished a bit I think.
any suggestions? just don't suggest boost typeof please! -- Pavel ps original code on codepad.org http://codepad.org/qXkESprl and following the discussion about codepad... the same code attached

DE wrote:
any suggestions? just don't suggest boost typeof please!
Why ? Because supporting non C++0X compiler is bad of course ... -- ___________________________________________ Joel Falcou - Assistant Professor PARALL Team - LRI - Universite Paris Sud XI Tel : (+33)1 69 15 66 35

on 01.02.2010 at 21:32 joel falcou wrote :
DE wrote:
any suggestions? just don't suggest boost typeof please!
Why ? Because supporting non C++0X compiler is bad of course ...
because i don't like it i mean specifically the boost typeof solution not the upcoming (?) standard -- Pavel

DE wrote:
because i don't like it i mean specifically the boost typeof solution not the upcoming (?) standard
I don't like strawberries but I don't bolster other people to not like them. Boost.Typeof is oen of the most elegant solution of emulating typeof on non-supporting compiler while decltype and/or auto comes out. Supporting those kind of compiler may be reuqired by some use cases. -- ___________________________________________ Joel Falcou - Assistant Professor PARALL Team - LRI - Universite Paris Sud XI Tel : (+33)1 69 15 66 35

on 01.02.2010 at 22:52 joel falcou wrote :
DE wrote:
because i don't like it i mean specifically the boost typeof solution not the upcoming (?) standard
I don't like strawberries but I don't bolster other people to not like them.
Boost.Typeof is oen of the most elegant solution of emulating typeof on non-supporting compiler while decltype and/or auto comes out. Supporting those kind of compiler may be reuqired by some use cases. sorry, i said what i said
and i never said that a boost feature must not be used in any case by anybody so i'm not sure what you are up to looks like kind of trolling -- Pavel

AMDG DE wrote:
on 01.02.2010 at 21:32 joel falcou wrote :
DE wrote:
any suggestions? just don't suggest boost typeof please!
Why ? Because supporting non C++0X compiler is bad of course ...
because i don't like it i mean specifically the boost typeof solution not the upcoming (?) standard
Might I point out that Boost.Typeof is a thin wrapper around typeof for compilers that support it. Boost.Typeof also has some evil hacks that allow it to work automatically on msvc even though msvc doesn't support typeof. In Christ, Steven Watanabe

Might I point out that Boost.Typeof is a thin wrapper around typeof for compilers that support it. Boost.Typeof also has some evil hacks that allow it to work automatically on msvc even though msvc doesn't support typeof. if this is adressed to me then thank you i'm aware that boost typeof wraps native facility and provide some emulation otherwise although i use primarily msvc i don't like the boost variant of typeof because coding for my own purposes doesn't need typeof and coding generically needs generic stable solutions in my opinion boost typeof is not generic enough
on 02.02.2010 at 0:46 Steven Watanabe wrote : that's why i don't like it so i decided not to use boost typeof and wait for the new standard -- Pavel

DE wrote:
although i use primarily msvc i don't like the boost variant of typeof because coding for my own purposes doesn't need typeof and coding generically needs generic stable solutions in my opinion boost typeof is not generic enough that's why i don't like i uh wut ?
Care to enligthen us on the non generic part of boost.Typeof ??? -- ___________________________________________ Joel Falcou - Assistant Professor PARALL Team - LRI - Universite Paris Sud XI Tel : (+33)1 69 15 66 35

on 02.02.2010 at 20:16 joel falcou wrote :
DE wrote:
although i use primarily msvc i don't like the boost variant of typeof because coding for my own purposes doesn't need typeof and coding generically needs generic stable solutions in my opinion boost typeof is not generic enough that's why i don't like i uh wut ?
Care to enligthen us on the non generic part of boost.Typeof ???
the part where some types must be registered prior to use you can not predict the usage of your code by third party so you can not control things on the user side proper setup for boost typeof is among them maybe i used the wrong word i meant that everything should work right out of the box -- Pavel

On Fri, Jan 29, 2010 at 12:47 PM, DE <satan66613@yandex.ru> wrote:
hi boosters while solving my own design problems i accidentally discovered an interesting technique
let's assume we want to associate some value (a type) to a newly created type so we can easily access the associated type during metaprogramming let's call the associated type a property then we have the following property types: [snip]
I can see this being very useful for traits class specializations (by that I mean the technique of using ADL to provide a type). As a practical example of why this is convenient in practice is Boost.Fusion. As a part of the library, there is a helper macro called BOOST_FUSION_ADAPT_STRUCT which, as the name suggests, maps a struct to the fusion random access sequence concept. When using the macro you have to do so at global scope since it has to specialize templates in a boost namespace. If, instead, the default definitions of these templates being specialized were altered to use an ADL trick, you could easily create a BOOST_FUSION_ADAPT_STRUCT macro that were usable from within the namespace itself. You'd no longer have to leave the namespace simply to use the macro. All fusion would have to do is declare a dummy "no_specialization get_traits(...);" kind of function in its own namespace, then have the default definition of its traits detect if the return type of a call to it using the specified type is "no_specialization". If not, that means that traits were provided by the type via ADL and can be used accordingly. Really, it would be convenient if all traits templates used this technique. -- -Matt Calabrese

on 30.01.2010 at 0:06 Matt Calabrese wrote :
I can see this being very useful for traits class specializations (by that I mean the technique of using ADL to provide a type). As a practical example of why this is convenient in practice is Boost.Fusion. As a part of the library, there is a helper macro called BOOST_FUSION_ADAPT_STRUCT which, as the name suggests, maps a struct to the fusion random access sequence concept. When using the macro you have to do so at global scope since it has to specialize templates in a boost namespace. If, instead, the default definitions of these templates being specialized were altered to use an ADL trick, you could easily create a BOOST_FUSION_ADAPT_STRUCT macro that were usable from within the namespace itself. You'd no longer have to leave the namespace simply to use the macro. All fusion would have to do is declare a dummy "no_specialization get_traits(...);" kind of function in its own namespace, then have the default definition of its traits detect if the return type of a call to it using the specified type is "no_specialization". If not, that means that traits were provided by the type via ADL and can be used accordingly.
Really, it would be convenient if all traits templates used this technique.
i'm happy this "by product" of design works elsewhere besides my scope by the way it compiles with msvc2005, icc11 and g++ (codepad.org version) so the the portability shouldn't be an issue although i didn't try other compilers -- Pavel
participants (5)
-
DE
-
joel falcou
-
Matt Calabrese
-
Simonson, Lucanus J
-
Steven Watanabe