[typeof-users] Looking for a consistent scheme for adding Typeof support to Boost libraries

Dear Boost developers, based on some experiments which I recently made with Typeof and Spirit, Joel de Guzman asked me if I would like to add "official" Typeof support to Spirit and got me in touch with Dan Marsden, who recently added experimental Typeof support to Phoenix2. Dan and I started discussing how Typeof support could look like for the two libraries and agreed in one important point: things should be consistent. Dan pointed out to me that it would be best to use a consistent scheme for adding Typeof support not only for Spirit and Phoenix2 but for all Boost libraries and therefore suggested shifting the discussion (previously in private email) to the Boost developers mailinglist. There are some suggestion on how such a scheme could look like at the end of this post. I'm looking forward to your comments. Thanks, Tobias Suggestions on possible schemes: ( 'a_lib' in the examples denotes a placholder for the name of the library, 'a_component.hpp' denotes the name of a public header of the library. ) 1. Create a 'typeof_support' directory reflecting the public headers of the library. The user enables Typeof support by including additional headers. Example: #include <boost/a_lib/a_component.hpp> // ^^^ usual library header #include <boost/a_lib/typeof_support/a_component.hpp> // ^^^ contains the registration for the header above 2. The Typeof registration is done in one separate header per library (module) that checks the include guards to register the components, where the registration is guarded by "registration guards" (as suggested by Arkadiy Vertleyb in the "Typeof and MPL" thread). The user enables Typeof support for the whole library by including a single header. Example: #include <boost/a_lib/a_component.hpp> #include <boost/a_lib/typeof_support.hpp> // The typeof_support header would do the following: // - Check the include guard macros to see which files have been // included // +-- For each of these files: register the components defined within // (guarded by a "registration guard macro") // - Define a macro to notify library headers #includeD later that the // Typeof support header has to be re-#includeD // (for large libraries this approach can be applied on a per-module basis) 3. The Typeof registration is put into the library's headers protected by some conditional. The user enables (or disables) Typeof support by defining a macro. Example: #define BOOST_A_LIB_TYPEOF_SUPPORT // ^^^ (or even do it in the Jamfile) #include <boost/a_lib/a_component.hpp>

"Tobias Schwinger" wrote
Dear Boost developers,
In the my limited experience of using Boost.Typeof as a user, I have found that I only needed to register at most a few types (mostly mpl), and was unhappy in the situation where the only choice is that all types in every header dependency known or unknown got registered. I appreciate that in many cases the specialisations are relatively simple but if there is a large number of specialisations it will eventually have a noticeable effect on compilation times. In the case of libraries of components such as mpl therefore, if possible I would prefer the 1st option over the 2nd and 3rd and would be happy to use the convention of a directory named typeof_support (or just typeof?) which user would add to component include path to use versions of the component that included typeof registration. Of course the above approach is the most complicated, much more fussy than simply registering everything at once, but I would think that needing to register only a few components rather than everything that might possibly need to be registered in a particular library is the most likely requirement? Thanks anyway for working to sort this out. reagrds Andy Little

"Andy Little" <andy@servocomm.freeserve.co.uk> wrote
if there is a large number of specialisations it will eventually have a noticeable effect on compilation times.
According to "C++ template metaprogramming" (C.3.5) though, this effect can be ignored. Regards, Arkadiy

"Arkadiy Vertleyb" wrote
"Andy Little" wrote
if there is a large number of specialisations it will eventually have a noticeable effect on compilation times.
According to "C++ template metaprogramming" (C.3.5) though, this effect can be ignored.
Ok I would still argue against registering evrything at once just for reasons of tidiness. OK I appreciate that its much more work though, so my 2nd choice would be to go for the 2nd approach where a common named file is included to register all the types for a library: 1 personal 'thing' for minimising macros 2 its easier to catch errors in a file name than #ifdef X 3 Its slightly more work figuring out the correct macro name than one common file name 4 Single file approach easier to manage as all registrations are in one place. Has the third approach using a macro got any advantages over file inclusion (2nd) approach? regards Andy Little

On 1/19/06, Andy Little <andy@servocomm.freeserve.co.uk> wrote:
"Arkadiy Vertleyb" wrote
"Andy Little" wrote
if there is a large number of specialisations it will eventually have a noticeable effect on compilation times.
According to "C++ template metaprogramming" (C.3.5) though, this effect can be ignored.
Ok I would still argue against registering evrything at once just for reasons of tidiness. OK I appreciate that its much more work though, so my 2nd choice would be to go for the 2nd approach where a common named file is included to register all the types for a library:
1 personal 'thing' for minimising macros 2 its easier to catch errors in a file name than #ifdef X 3 Its slightly more work figuring out the correct macro name than one common file name 4 Single file approach easier to manage as all registrations are in one place.
Has the third approach using a macro got any advantages over file inclusion (2nd) approach?
Personally, I don't like the 2nd approach, as it introduces include order dependencies, <boost/a_lib/a_component.hpp> must be included prior to including <boost/a_lib/typeof_support.hpp> Creating a header called my_includes.hpp that contains: #include <boost/a_lib/a_component.hpp> #include <boost/a_lib/typeof_support.hpp> and in my_program.cpp including #include <my_includes.hpp> #include <boost/a_lib/another_component.hpp> gives a different behaviour from #include <boost/a_lib/another_component.hpp> #include <my_includes.hpp>
From my perspective, this is unacceptable.
Regards, Peder
regards Andy Little
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Peder Holt wrote:
On 1/19/06, Andy Little <andy@servocomm.freeserve.co.uk> wrote:
Personally, I don't like the 2nd approach, as it introduces include order dependencies, <boost/a_lib/a_component.hpp> must be included prior to including <boost/a_lib/typeof_support.hpp>
Creating a header called my_includes.hpp that contains: #include <boost/a_lib/a_component.hpp> #include <boost/a_lib/typeof_support.hpp> and in my_program.cpp including
#include <my_includes.hpp> #include <boost/a_lib/another_component.hpp>
gives a different behaviour from
There should only be a slight difference in terms of compile time -- except this effect the behaviour should be identical.
#include <boost/a_lib/another_component.hpp> #include <my_includes.hpp>
From my perspective, this is unacceptable.
I believe here's a misunderstanding. Did your read http://article.gmane.org/gmane.comp.lib.boost.devel/136946 (guessing from the time stamp you probably couldn't)? Or am /I/ eventually missing something? Regards, Tobias

On 1/19/06, Tobias Schwinger <tschwinger@neoscientists.org> wrote:
Peder Holt wrote:
On 1/19/06, Andy Little <andy@servocomm.freeserve.co.uk> wrote:
Personally, I don't like the 2nd approach, as it introduces include order dependencies, <boost/a_lib/a_component.hpp> must be included prior to including <boost/a_lib/typeof_support.hpp>
Creating a header called my_includes.hpp that contains: #include <boost/a_lib/a_component.hpp> #include <boost/a_lib/typeof_support.hpp> and in my_program.cpp including
#include <my_includes.hpp> #include <boost/a_lib/another_component.hpp>
gives a different behaviour from
There should only be a slight difference in terms of compile time -- except this effect the behaviour should be identical.
#include <boost/a_lib/another_component.hpp> #include <my_includes.hpp>
From my perspective, this is unacceptable.
I believe here's a misunderstanding. Did your read
http://article.gmane.org/gmane.comp.lib.boost.devel/136946
(guessing from the time stamp you probably couldn't)?
Or am /I/ eventually missing something?
My understanding of the solution: 1. typeof_support.hpp uses include-guard defines to filter which components to register to typeof. 2. Any component included AFTER typeof_support.hpp will not have typeof_support, as their include-guards have not been triggered at the point of including typeof_support.hpp #include <my_includes.hpp> #include <boost/a_lib/another_component.hpp> will not register the another_component with typeof, but #include <boost/a_lib/another_component.hpp> #include <my_includes.hpp> will. Is there something I haven't understood? Regards, Peder
Regards,
Tobias
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Peder Holt wrote:
On 1/19/06, Tobias Schwinger <tschwinger@neoscientists.org> wrote:
2. Any component included AFTER typeof_support.hpp will not have typeof_support, as their include-guards have not been triggered at the point of including typeof_support.hpp
Every component included after typeof_support.hpp will re-include typeof_support.hpp at the end of the header. There is an example on the implementation structure of the 2nd scenario elsewhere in this thread (pointed to by the link in my previous post). Regards, Tobias

On 1/19/06, Tobias Schwinger <tschwinger@neoscientists.org> wrote:
Peder Holt wrote:
On 1/19/06, Tobias Schwinger <tschwinger@neoscientists.org> wrote:
2. Any component included AFTER typeof_support.hpp will not have typeof_support, as their include-guards have not been triggered at the point of including typeof_support.hpp
Every component included after typeof_support.hpp will re-include typeof_support.hpp at the end of the header.
There is an example on the implementation structure of the 2nd scenario elsewhere in this thread (pointed to by the link in my previous post).
Ahh, I see. Sorry. That would work. Regards, Peder
Regards,
Tobias
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

"Peder Holt" wrote
Personally, I don't like the 2nd approach, as it introduces include order dependencies, <boost/a_lib/a_component.hpp> must be included prior to including <boost/a_lib/typeof_support.hpp>
Creating a header called my_includes.hpp that contains: #include <boost/a_lib/a_component.hpp> #include <boost/a_lib/typeof_support.hpp> and in my_program.cpp including
#include <my_includes.hpp> #include <boost/a_lib/another_component.hpp>
gives a different behaviour from
#include <boost/a_lib/another_component.hpp> #include <my_includes.hpp>
From my perspective, this is unacceptable.
OK I see thats no good, so how about the 3rd approach? Each library needs to detect if a Macro with a common format is defined and if it is do (one-time) typeof registration. That would make that approach best from point of simplicity. A global macro which triggers the per library macro could be possible too for a user that is feeling lazy about figuring out which libraries to register. regards Andy Little

Andy Little wrote:
"Tobias Schwinger" wrote
Dear Boost developers,
In the my limited experience of using Boost.Typeof as a user, I have found that I only needed to register at most a few types (mostly mpl), and was unhappy in the situation where the only choice is that all types in every header dependency known or unknown got registered.
Good point. For "expression template libraries" such as Spirit, Bind, Lamda or Phoenix it's not necessary to register everything. What needs to be registered are only the templates and types that end up in the expression type: Say we an expression like some_p(param) >> "foo" 'some_p' might be a function template defined like this template<typename T> typename some_p_result<T>::type some_p(T const & param) { [...] } We should only register the components that may end up in the actual expression: sequence< some_parser< maybe_a_user_type >, strlit<char> > and not bother with the 'some_p_result' metafunction in this example. For libraries such as MPL and especially Fusion it will be more difficult to decide what needs to be registered although my guess is that (in the particular case of MPL) it will be enough to register the sequences and constant wrappers, because MPL programs are written as types and not as expressions. Maybe Dan can add some details on the Fusion case.
I appreciate that in many cases the specialisations are relatively simple but if there is a large number of specialisations it will eventually have a noticeable effect on compilation times. In the case of libraries of components such as mpl therefore, if possible I would prefer the 1st option over the 2nd and 3rd and would be happy to use the convention of a directory named typeof_support (or just typeof?)
which user would add to component include path to use versions of the component that included typeof registration.
Another good idea! If changing the include path should work to globally enable Typeof support we'd need a 'boost' directory under 'typeof' (or 'typeof_support'), though.
Of course the above approach is the most complicated, much more fussy than simply registering everything at once, but I would think that needing to register only a few components rather than everything that might possibly need to be registered in a particular library is the most likely requirement?
Well, it depends on the case. For Spirit I'd usually want Typeof support for all the components I use, but the case might not be representative.
Thanks anyway for working to sort this out.
Thank you for your reply! -- Tobias

Suggestions on possible schemes:
( 'a_lib' in the examples denotes a placholder for the name of the
'a_component.hpp' denotes the name of a public header of the library. )
1. Create a 'typeof_support' directory reflecting the public headers of
"Tobias Schwinger" <tschwinger@neoscientists.org> wrote library, the
library. The user enables Typeof support by including additional headers.
Example:
#include <boost/a_lib/a_component.hpp> // ^^^ usual library header #include <boost/a_lib/typeof_support/a_component.hpp> // ^^^ contains the registration for the header above
This scheme looks similar to what we've done with std headers. It may make sense for typeof_support/a_component.hpp to include a_component.hpp.
2. The Typeof registration is done in one separate header per library (module) that checks the include guards to register the components,
Thus avoiding the nead to forward-declare everything?
where the registration is guarded by "registration guards" (as suggested by Arkadiy Vertleyb in the "Typeof and MPL" thread).
The user enables Typeof support for the whole library by including a single header.
Example:
#include <boost/a_lib/a_component.hpp> #include <boost/a_lib/typeof_support.hpp> // The typeof_support header would do the following: // - Check the include guard macros to see which files have been // included // +-- For each of these files: register the components defined within // (guarded by a "registration guard macro") // - Define a macro to notify library headers #includeD later that
It was first suggested by David Abrahams, and was meant to synchronize registrations of the same library done by different library users. What you are suggesting sounds like a new idea to me, and I am not sure I completely understand this. Can you ellaborate? the
// Typeof support header has to be re-#includeD // (for large libraries this approach can be applied on a per-module
basis)
3. The Typeof registration is put into the library's headers protected by
some
conditional. The user enables (or disables) Typeof support by defining a macro.
Example:
#define BOOST_A_LIB_TYPEOF_SUPPORT // ^^^ (or even do it in the Jamfile) #include <boost/a_lib/a_component.hpp>
Regards, Arkadiy

Arkadiy Vertleyb wrote:
"Tobias Schwinger" <tschwinger@neoscientists.org> wrote
1. Create a 'typeof_support' directory reflecting the public headers of the library. The user enables Typeof support by including additional headers.
Example:
#include <boost/a_lib/a_component.hpp> // ^^^ usual library header #include <boost/a_lib/typeof_support/a_component.hpp> // ^^^ contains the registration for the header above
This scheme looks similar to what we've done with std headers. It may make sense for typeof_support/a_component.hpp to include a_component.hpp.
2. The Typeof registration is done in one separate header per library (module) that checks the include guards to register the components,
Thus avoiding the nead to forward-declare everything?
Well this need could be avoided in case 1) as well by making the typeof header include the library header it reflects...
where the registration is guarded by "registration guards" (as suggested by Arkadiy Vertleyb in the "Typeof and MPL" thread).
It was first suggested by David Abrahams, and was meant to synchronize registrations of the same library done by different library users. What you are suggesting sounds like a new idea to me, and I am not sure I completely understand this. Can you ellaborate?
The library would implement typeof support like this: --- boost/<LIB>/typeof_support.hpp #if !defined(<LIB>_TYPEOF_SUPPORT) # define <LIB>_TYPEOF_SUPPORT #endif #if defined(<include guard macro 1st file>) # if !defined(<typeof guard macro 1st file>) # define <typeof guard macro 1st file> // <-- register components in file 1 here # endif #endif #if defined(<include guard macro 2nd file>) # if !defined(<typeof guard macro 2nd file>) # define <typeof guard macro 2nd file> // <-- register components in file 2 here # endif #endif // [...] --- at the end of every source file: #if defined(<LIB>_TYPEOF_SUPPORT) # include <boost/<LIB>/typeof_support.hpp> #endif This technique could be applied: - in combination with 1) to allow maximum convenience - or per-module bases having a global typeof_support header for the library that includes the typeof_support headers for its modules.
The user enables Typeof support for the whole library by including a single header.
Example:
#include <boost/a_lib/a_component.hpp> #include <boost/a_lib/typeof_support.hpp> // The typeof_support header would do the following: // - Check the include guard macros to see which files have been // included // +-- For each of these files: register the components defined within // (guarded by a "registration guard macro") // - Define a macro to notify library headers #includeD later that the // Typeof support header has to be re-#includeD // (for large libraries this approach can be applied on a per-module basis)
Hope it helps. Regards, Tobias

"Tobias Schwinger" <tschwinger@neoscientists.org> wrote
The library [option #2] would implement typeof support like this:
--- boost/<LIB>/typeof_support.hpp
#if !defined(<LIB>_TYPEOF_SUPPORT) # define <LIB>_TYPEOF_SUPPORT #endif
#if defined(<include guard macro 1st file>) # if !defined(<typeof guard macro 1st file>) # define <typeof guard macro 1st file> // <-- register components in file 1 here # endif #endif
#if defined(<include guard macro 2nd file>) # if !defined(<typeof guard macro 2nd file>) # define <typeof guard macro 2nd file> // <-- register components in file 2 here # endif #endif
// [...]
--- at the end of every source file:
#if defined(<LIB>_TYPEOF_SUPPORT) # include <boost/<LIB>/typeof_support.hpp> #endif
OK, understand. The last lines above make this solution intrusive, and #3 is intrusive as well... What are the drawbacks of #1? Regards, Arkadiy

Arkadiy Vertleyb wrote:
"Tobias Schwinger" <tschwinger@neoscientists.org> wrote
// [...]
--- at the end of every source file:
#if defined(<LIB>_TYPEOF_SUPPORT) # include <boost/<LIB>/typeof_support.hpp> #endif
^^^^ The conditional could be factored out into another header file...
OK, understand. The last lines above make this solution intrusive, and #3 is intrusive as well...
Why is "intrusiveness" undesirable in this context?
What are the drawbacks of #1?
OK let's summarize pro (donted by +) and contra (denoted by -): 1) + fine grained control for the user + global typeof support could be made possible by adding include directory (when there is a 'boost' directory) - it dictates the granularity and thus imposes a lot of work on the library authors who want to add Typeof support - we'll end up with a huge ammount of headers, each with a license and an include guard and most of these headers will only contain one or two lines of effective code, thus bloating up the Boost distribution - the "non-intrusiveness" can be seen as a drawback, because the otherwise there is a "reminder" to each header not to forget the Typeof registration when changing things (granted, it's an arguable point). 2) + library authors can freely choose the granularity level for doing the registration + it can be used in combination with #1 in cases where more fine grained control over Typeof support makes sense - it's quite complicated 3) + it's very simple - only global support is possible - it uses a macro for the configuration Regards, Tobias

"Tobias Schwinger" <tschwinger@neoscientists.org> wrote
Arkadiy Vertleyb wrote:
"Tobias Schwinger" <tschwinger@neoscientists.org> wrote
// [...]
--- at the end of every source file:
#if defined(<LIB>_TYPEOF_SUPPORT) # include <boost/<LIB>/typeof_support.hpp> #endif
^^^^ The conditional could be factored out into another header file...
OK, understand. The last lines above make this solution intrusive, and
#3
is intrusive as well...
Why is "intrusiveness" undesirable in this context?
1) A library may be targeted for inclusion into the Standard, in which case it would not be appropriate for it to depend on typeof. 2) The typeof library is a temporary solution. Once the typeof operator is in the Standard, and is implemented by the compiler vendors, and Boost no longer supports any legacy compiler with no native typeof, the registration stuff will need to be removed. It's a little easier to do if done non-intrusively. 3) It might be nice to have a similar scheme for Boost libraries and for the Standard Library. The latter, obviously, can't be done intrusively.
2)
+ library authors can freely choose the granularity level for doing the registration + it can be used in combination with #1 in cases where more fine grained control over Typeof support makes sense - it's quite complicated
- it introduces unnecessary dependencies -- when a type is added/changed this is reflected in the header that is used by the clients having nothing to do with this type. Regards, Arkadiy

Arkadiy Vertleyb wrote:
"Tobias Schwinger" <tschwinger@neoscientists.org> wrote
Why is "intrusiveness" undesirable in this context?
1) A library may be targeted for inclusion into the Standard, in which case it would not be appropriate for it to depend on typeof.
2) The typeof library is a temporary solution. Once the typeof operator is in the Standard, and is implemented by the compiler vendors, and Boost no longer supports any legacy compiler with no native typeof, the registration stuff will need to be removed. It's a little easier to do if done non-intrusively.
3) It might be nice to have a similar scheme for Boost libraries and for the Standard Library. The latter, obviously, can't be done intrusively.
OK.
2)
+ library authors can freely choose the granularity level for doing the registration + it can be used in combination with #1 in cases where more fine grained control over Typeof support makes sense - it's quite complicated
- it introduces unnecessary dependencies -- when a type is added/changed this is reflected in the header that is used by the clients having nothing to do with this type.
^^^ Sorry, I don't understand this sentence. Would you elaborate, please? Well, I guess we're going to go for #1 then. Where should the header go? boost/typeof/boost/<LIB> ?? Regards, Tobias

"Tobias Schwinger" <tschwinger@neoscientists.org> wrote
- it introduces unnecessary dependencies -- when a type is added/changed this is reflected in the header that is used by the clients having nothing to do with this type.
^^^ Sorry, I don't understand this sentence. Would you elaborate, please?
If I have all the types registered in the same header, and if I add a new type, then this registration header needs to be modified to register the new type. At this point I have to rebuild all the sources that use typeof on _any_ type.
Well, I guess we're going to go for #1 then.
Well, I just pointed out a few benefits of #1, but I am by no means sure that it's perfect, and even the best of three...
Where should the header go?
boost/typeof/boost/<LIB>
??
No, definitely not under boost/typeof :-) I think the registration should be [conceptualy] owned by the library authors rather then typeof library, so I still think boost/<LIB>/typeof is more appropriate. When I was talking about non-intrusiveness I meant files, not directories. It is also much easier to work with CVS when everything is under the same root. Regards, Arkadiy

--- Arkadiy Vertleyb <vertleyb@hotmail.com> wrote:
Where should the header go?
boost/typeof/boost/<LIB>
??
No, definitely not under boost/typeof :-)
I think the registration should be [conceptualy] owned by the library authors rather then typeof library, so I still think boost/<LIB>/typeof is more appropriate. When I was talking about non-intrusiveness I meant files, not directories. It is also much easier to work with CVS when everything is under the same root.
That sounds reasonable to me. The various macro approaches seem a bit too clever, a header based approach should be easy for library clients to understand. As for structure, how about consistently placing the typeof headers in a directory beneath the file they support. So for a file: boost/a/b/c.hpp The corresponding typeof support would be in: boost/a/b/typeof/c.hpp So for a small part of phoenix2 for example we have: boost/spirit/phoenix/operator/arithmetic.hpp boost/spirit/phoenix/operator/logical.hpp etc... Which provide lamdba support for different types of operators. Their typeof support would be in: boost/spirit/phoenix/operator/typeof/arithmetic.hpp boost/spirit/phoenix/operator/typeof/logical.hpp etc... Phoenix also provides a single file that provides all the operator support in one hit: boost/spirit/phoenix/operator.hpp Again following the same logic, to add all the corresponding typeof support: boost/spirit/phoenix/typeof/operator.hpp Hopefully that illustrates one possible candidate naming scheme. I've aimed for simplicity, consistency and fine grain control over what typeof support is brought in. The higher level files (like operator.hpp) allow clients that are not fussy to just drag in a load of typeof support in one hit. At least one downside is that there are a lot of additional files for library writers to manage in some of the more complex libraries. Cheers Dan ___________________________________________________________ Yahoo! Photos – NEW, now offering a quality print service from just 8p a photo http://uk.photos.yahoo.com

dan marsden wrote:
--- Arkadiy Vertleyb <vertleyb@hotmail.com> wrote:
Where should the header go?
boost/typeof/boost/<LIB>
??
No, definitely not under boost/typeof :-)
I think the registration should be [conceptualy] owned by the library authors rather then typeof library, so I still think boost/<LIB>/typeof is more appropriate. When I was talking about non-intrusiveness I meant files, not directories. It is also much easier to work with CVS when everything is under the same root.
That sounds reasonable to me. The various macro approaches seem a bit too clever, a header based approach should be easy for library clients to understand.
As for structure, how about consistently placing the typeof headers in a directory beneath the file they support. So for a file:
boost/a/b/c.hpp
The corresponding typeof support would be in:
boost/a/b/typeof/c.hpp
So for a small part of phoenix2 for example we have:
boost/spirit/phoenix/operator/arithmetic.hpp boost/spirit/phoenix/operator/logical.hpp etc...
Which provide lamdba support for different types of operators. Their typeof support would be in:
boost/spirit/phoenix/operator/typeof/arithmetic.hpp boost/spirit/phoenix/operator/typeof/logical.hpp etc...
Phoenix also provides a single file that provides all the operator support in one hit:
boost/spirit/phoenix/operator.hpp
Again following the same logic, to add all the corresponding typeof support:
boost/spirit/phoenix/typeof/operator.hpp
Hopefully that illustrates one possible candidate naming scheme. I've aimed for simplicity, consistency and fine grain control over what typeof support is brought in. The higher level files (like operator.hpp) allow clients that are not fussy to just drag in a load of typeof support in one hit. At least one downside is that there are a lot of additional files for library writers to manage in some of the more complex libraries.
I think I like this best. Regards, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net

dan marsden wrote:
--- Arkadiy Vertleyb <vertleyb@hotmail.com> wrote:
As for structure, how about consistently placing the typeof headers in a directory beneath the file they support. So for a file:
boost/a/b/c.hpp
The corresponding typeof support would be in:
boost/a/b/typeof/c.hpp
A single-rooted approach might still be better: boost/a/typeof/boost/a/b/c.hpp or even (although Arkadiy pointed out it would be less CVS-friendly) boost/typeof_support/boost/a/b/c.hpp Now I could switch my include path to contain boost/a/typeof or to boost/typeof_support respectively and thus enable typeof support for lib a without changing my source code (as suggested by Andy elsewhere in this thread). Of course this would require us to #include <../../../../b/c.hpp> or #include <../../../a/b/c.hpp> from within */typeof*/boost/a/b/c.hpp. I've no idea whether this is acceptable or not. But we should probably spend a few thoughts on it. Regards, Tobias

"Tobias Schwinger" <tschwinger@neoscientists.org> wrote
A single-rooted approach might still be better:
boost/a/typeof/boost/a/b/c.hpp
or even (although Arkadiy pointed out it would be less CVS-friendly)
boost/typeof_support/boost/a/b/c.hpp
Now I could switch my include path to contain boost/a/typeof or to boost/typeof_support respectively and thus enable typeof support for lib a without changing my source code (as suggested by Andy elsewhere in this thread).
Note that disabling typeof support seems to be easily achieved by just defining BOOST_TYPEOF_NATIVE, which forces all the registrations to be no-op. Regards, Arkadiy

Arkadiy Vertleyb wrote:
"Tobias Schwinger" <tschwinger@neoscientists.org> wrote
A single-rooted approach might still be better:
boost/a/typeof/boost/a/b/c.hpp
or even (although Arkadiy pointed out it would be less CVS-friendly)
boost/typeof_support/boost/a/b/c.hpp
Now I could switch my include path to contain boost/a/typeof or to boost/typeof_support respectively and thus enable typeof support for lib a without changing my source code (as suggested by Andy elsewhere in this thread).
Note that disabling typeof support seems to be easily achieved by just defining BOOST_TYPEOF_NATIVE, which forces all the registrations to be no-op.
Yeah, right. Although that's not quite the same, is it? Say I have an existing project and want to start using Typeof. There might me a lot of already-written source code and I'd have to change all the includes therein that refer to the libraries I want Typeof support for. As an end user, I would definitely prefer changing my include directory over changing all the includes (especially considering your own point that the Typeof library is only a temporary solution). The situation becomes even more delicate if I use a library that in turn uses a some part of Boost. Now I can either go through the foreign code and figure out what needs to be included or include Typeof support for the whole part of Boost my library depends on. Regards, Tobias

Say I have an existing project and want to start using Typeof. There might me a lot of already-written source code and I'd have to change all the includes
"Tobias Schwinger" <tschwinger@neoscientists.org> wrote therein
that refer to the libraries I want Typeof support for. As an end user, I would definitely prefer changing my include directory over changing all the includes (especially considering your own point that the Typeof library is only a temporary solution).
The situation becomes even more delicate if I use a library that in turn uses a some part of Boost. Now I can either go through the foreign code and
OTOH, it doesn't seem very likely that somebody would need such a global one-time switch to typeof support. Most likely typeof is going to be introduced gradually, as new features are added, and the old ones are re-factored. In such case changing the include dir would cause undesirable rebuild of the whole project. It's easier to imagine the global backward switch from typeof, though... figure out
what needs to be included or include Typeof support for the whole part of Boost my library depends on.
Can the registration headers mirror dependency structure of the original files, such as: boost/<LIB>/h.hpp #include "boost/<LIB>/h1.hpp" #include "boost/<LIB>/h2.hpp" ... boost/<LIB>/typeof/h.hpp // include original file #include "boost<LIB>/h.hpp" // register types in the original file REGISTER_TYPE... // register included types #include "boost/<LIB>/typeof/h1.hpp" #include "boost/<LIB>/typeof/h2.hpp" ? Regards, Arkadiy

Arkadiy Vertleyb wrote:
"Tobias Schwinger" <tschwinger@neoscientists.org> wrote
Say I have an existing project and want to start using Typeof. There might me a lot of already-written source code and I'd have to change all the includes therein that refer to the libraries I want Typeof support for. As an end user, I would definitely prefer changing my include directory over changing all the includes (especially considering your own point that the Typeof library is only a temporary solution).
OTOH, it doesn't seem very likely that somebody would need such a global one-time switch to typeof support. Most likely typeof is going to be introduced gradually, as new features are added, and the old ones are re-factored.
The assumption is based on ... ? I guess here's a misunderstanding: my argumentation comes from an end-user's perspective (I'm not talking about library development). An exemplary use case could be to optimize an existing Spirit parser with Typeof.
In such case changing the include dir would cause undesirable rebuild of the whole project. It's easier to imagine the global backward switch from typeof, though...
A rebuild should still be faster (and more fun -- get some coffee ;-) ) than manually applying repetitive changes. If it's not, your project is probably too large and you should factor something out into a library.
The situation becomes even more delicate if I use a library that in turn uses a some part of Boost. Now I can either go through the foreign code and figure out what needs to be included or include Typeof support for the whole part of Boost my library depends on.
Just to ensure we understand each other correctly: Boost.<LIB> ^ | third pary library (externalizes types from Boost.<LIB>) ^ | user code (wants to use Typeof on the types externalized by the library) (the arrow denotes a "depends on" relationship)
Can the registration headers mirror dependency structure of the original files, such as:
boost/<LIB>/h.hpp
#include "boost/<LIB>/h1.hpp" #include "boost/<LIB>/h2.hpp" ...
boost/<LIB>/typeof/h.hpp
// include original file #include "boost<LIB>/h.hpp"
// register types in the original file REGISTER_TYPE...
// register included types #include "boost/<LIB>/typeof/h1.hpp" #include "boost/<LIB>/typeof/h2.hpp"
?
They definitely should (although it won't solve the hypothetical problem described above)! And we can optimize boost/<LIB>/typeof/h.hpp to look like // Include Typeof #include <boost/typeof/typeof.hpp> // this header ^^^ should contain "#pagma once" for gcc >= 3.? and MSVC // Dependencies // (do not read and preprocess lots of files that will be empty anyway // for natively supported typeof) #if !defined(BOOST_TYPEOF_NATIVE) #include <boost/<LIB>/typeof/h1.hpp> #include <boost/<LIB>/typeof/h2.hpp> #endif // Original file #include <boost/<LIB>/h.hpp> // Registration BOOST_TYPEF_REGISTER_* , though. Regards, Tobias

Arkadiy Vertleyb wrote:
"Tobias Schwinger" <tschwinger@neoscientists.org> wrote
Say I have an existing project and want to start using Typeof. There might me a lot of already-written source code and I'd have to change all the includes therein that refer to the libraries I want Typeof support for. As an end user, I would definitely prefer changing my include directory over changing all the includes (especially considering your own point that
"Tobias Schwinger" <tschwinger@neoscientists.org> wrote the Typeof
library is only a temporary solution).
OTOH, it doesn't seem very likely that somebody would need such a global one-time switch to typeof support. Most likely typeof is going to be introduced gradually, as new features are added, and the old ones are re-factored.
The assumption is based on ... ?
I think we are talking about a large project (for small projects almost any strategy will be fine). In such large projects big amount of code is never touched. So, if somebody is working with some particular piece of code, and wants to use (or try) typeof for it, why rebuild everything? Also, even though the inclusion of typeof is quite cheap now (especially after your last improvement), it still has some price (mostly related to the preprocessing). Why pay this price compiling files that don't use typeof?
I guess here's a misunderstanding: my argumentation comes from an end-user's perspective (I'm not talking about library development).
An exemplary use case could be to optimize an existing Spirit parser with Typeof.
In such case changing the include dir would cause undesirable rebuild of the whole project. It's easier to imagine the global backward switch from typeof, though...
A rebuild should still be faster (and more fun -- get some coffee ;-) )
manually applying repetitive changes. If it's not, your project is
large and you should factor something out into a library.
The situation becomes even more delicate if I use a library that in turn uses a some part of Boost. Now I can either go through the foreign code and
what needs to be included or include Typeof support for the whole part of Boost my library depends on.
Just to ensure we understand each other correctly:
Boost.<LIB> ^ | third pary library (externalizes types from Boost.<LIB>) ^ | user code (wants to use Typeof on the types externalized by the
I understand this. than probably too figure out library)
(the arrow denotes a "depends on" relationship)
Can the registration headers mirror dependency structure of the original files, such as:
boost/<LIB>/h.hpp
#include "boost/<LIB>/h1.hpp" #include "boost/<LIB>/h2.hpp" ...
boost/<LIB>/typeof/h.hpp
// include original file #include "boost<LIB>/h.hpp"
// register types in the original file REGISTER_TYPE...
// register included types #include "boost/<LIB>/typeof/h1.hpp" #include "boost/<LIB>/typeof/h2.hpp"
?
They definitely should (although it won't solve the hypothetical problem
described
above)!
Why not? I don't understand... If, for example, a Spirit header includes an MPL header, the corresponding Spirit registration header would include the corresponding MPL registration header. So, if I include the Spirit registration header, I automatically get needed MPL types registered, won't I? === I think we pretty much have two main alternatives now (if I am missing something, please correct me): 1) The user gets typeof support for the whole project _automatically_ (possibly after defining some preprocessor constant, changing include path, etc.). The main drawback here seems to be the price to pay for inclusion typeof headers and registering types even in the translation units that never use typeof. 2) The user has to explicitly specify where he wants to use typeof (probably by the means of including registration headers instead of regular library headers). This does introduce some extra work, since as typeof is applied, the #include statements need to be modified. But, in general, this approach gives a more fine grain control over where typeof is included, and so will probably result in faster compiles (although I can't claim I have any idea on how noticable this will be). Regards, Arkadiy

Arkadiy Vertleyb wrote:
"Tobias Schwinger" <tschwinger@neoscientists.org> wrote
They definitely should (although it won't solve the hypothetical problem described above)!
Why not? I don't understand... If, for example, a Spirit header includes an MPL header, the corresponding Spirit registration header would include the corresponding MPL registration header.
So, if I include the Spirit registration header, I automatically get needed MPL types registered, won't I?
Spirit and MPL are both part of Boost. I was talking about a third party library in between user and Boost code.
I think we pretty much have two main alternatives now (if I am missing something, please correct me):
1) The user gets typeof support for the whole project _automatically_ (possibly after defining some preprocessor constant, changing include path, etc.). The main drawback here seems to be the price to pay for inclusion typeof headers and registering types even in the translation units that never use typeof.
2) The user has to explicitly specify where he wants to use typeof (probably by the means of including registration headers instead of regular library headers). This does introduce some extra work, since as typeof is applied, the #include statements need to be modified. But, in general, this approach gives a more fine grain control over where typeof is included, and so will probably result in faster compiles (although I can't claim I have any idea on how noticable this will be).
The post starting this discussion branch was about considering to allow 1) as a special case of 2). A directory structure like this could allow it boost/<LIB>/a.hpp boost/<LIB>/a/a1.hpp boost/<LIB>/a/a2.hpp boost/<LIB>/b.hpp boost/<LIB>/b/b1.hpp boost/<LIB>/b/b2.hpp boost/<LIB>/typeof/boost/<LIB>/a.hpp boost/<LIB>/typeof/boost/<LIB>/a/a1.hpp boost/<LIB>/typeof/boost/<LIB>/a/a2.hpp boost/<LIB>/typeof/boost/<LIB>/b.hpp boost/<LIB>/typeof/boost/<LIB>/b/b1.hpp boost/<LIB>/typeof/boost/<LIB>/b/b2.hpp a directory structure like this does (although it won't allow to switch typeof support on and off on a per-library basis) too boost/<LIB>/a.hpp boost/<LIB>/a/a1.hpp boost/<LIB>/a/a2.hpp boost/<LIB>/b.hpp boost/<LIB>/b/b1.hpp boost/<LIB>/b/b2.hpp typeof_support/boost/<LIB>/a.hpp typeof_support/boost/<LIB>/a/a1.hpp typeof_support/boost/<LIB>/a/a2.hpp typeof_support/boost/<LIB>/b.hpp typeof_support/boost/<LIB>/b/b1.hpp typeof_support/boost/<LIB>/b/b2.hpp a directory structure like this boost/<LIB>/a.hpp boost/<LIB>/typeof/a.hpp boost/<LIB>/a/a1.hpp boost/<LIB>/a/typeof/a1.hpp boost/<LIB>/a/a2.hpp boost/<LIB>/a/typeof/a2.hpp boost/<LIB>/b.hpp boost/<LIB>/typeof/b.hpp boost/<LIB>/b/b1.hpp boost/<LIB>/b/typeof/b1.hpp boost/<LIB>/b/b2.hpp boost/<LIB>/b/typeof/b2.hpp does not. I'm not at all sure it's a good idea in the first place. Further the former two alternatives require us to #include <../../../boost/<LIB>/whatever.hpp> (that is if the include dir switch should work) and I don't know whether this is a clean solution, either. However, I think we should carefully investigate opportunities like this one because once we decide on something we should stick to it. If there's written code it will be tedious work to change it... Regards, Tobias

Arkadiy Vertleyb wrote:
"Tobias Schwinger" <tschwinger@neoscientists.org> wrote
They definitely should (although it won't solve the hypothetical problem described above)!
Why not? I don't understand... If, for example, a Spirit header includes an MPL header, the corresponding Spirit registration header would include the corresponding MPL registration header.
So, if I include the Spirit registration header, I automatically get needed MPL types registered, won't I?
Spirit and MPL are both part of Boost. I was talking about a third party
"Tobias Schwinger" <tschwinger@neoscientists.org> wrote library
in between user and Boost code.
I think we pretty much have two main alternatives now (if I am missing something, please correct me):
1) The user gets typeof support for the whole project _automatically_ (possibly after defining some preprocessor constant, changing include
etc.). The main drawback here seems to be the price to pay for inclusion typeof headers and registering types even in the translation units that never use typeof.
2) The user has to explicitly specify where he wants to use typeof (probably by the means of including registration headers instead of regular
In my above statement replace "Spirit" with "third party library". What is going to change? path, library
headers). This does introduce some extra work, since as typeof is applied, the #include statements need to be modified. But, in general, this approach gives a more fine grain control over where typeof is included, and so will probably result in faster compiles (although I can't claim I have any idea on how noticable this will be).
The post starting this discussion branch was about considering to allow 1) as a special case of 2).
A directory structure like this could allow it
boost/<LIB>/a.hpp boost/<LIB>/a/a1.hpp boost/<LIB>/a/a2.hpp boost/<LIB>/b.hpp boost/<LIB>/b/b1.hpp boost/<LIB>/b/b2.hpp boost/<LIB>/typeof/boost/<LIB>/a.hpp boost/<LIB>/typeof/boost/<LIB>/a/a1.hpp boost/<LIB>/typeof/boost/<LIB>/a/a2.hpp boost/<LIB>/typeof/boost/<LIB>/b.hpp boost/<LIB>/typeof/boost/<LIB>/b/b1.hpp boost/<LIB>/typeof/boost/<LIB>/b/b2.hpp
a directory structure like this does (although it won't allow to switch typeof support on and off on a per-library basis) too
boost/<LIB>/a.hpp boost/<LIB>/a/a1.hpp boost/<LIB>/a/a2.hpp boost/<LIB>/b.hpp boost/<LIB>/b/b1.hpp boost/<LIB>/b/b2.hpp typeof_support/boost/<LIB>/a.hpp typeof_support/boost/<LIB>/a/a1.hpp typeof_support/boost/<LIB>/a/a2.hpp typeof_support/boost/<LIB>/b.hpp typeof_support/boost/<LIB>/b/b1.hpp typeof_support/boost/<LIB>/b/b2.hpp
a directory structure like this
boost/<LIB>/a.hpp boost/<LIB>/typeof/a.hpp boost/<LIB>/a/a1.hpp boost/<LIB>/a/typeof/a1.hpp boost/<LIB>/a/a2.hpp boost/<LIB>/a/typeof/a2.hpp boost/<LIB>/b.hpp boost/<LIB>/typeof/b.hpp boost/<LIB>/b/b1.hpp boost/<LIB>/b/typeof/b1.hpp boost/<LIB>/b/b2.hpp boost/<LIB>/b/typeof/b2.hpp
does not.
I'm not at all sure it's a good idea in the first place. Further the former two alternatives require us to
#include <../../../boost/<LIB>/whatever.hpp>
(that is if the include dir switch should work) and I don't know whether
OK, understood. this is a
clean solution, either.
I don't think I like this. Somehow I am not really comfortable with the idea of using the include path to "trick" the compiler into including the registration file when it seems from the code that just the regular header is included...
However, I think we should carefully investigate opportunities like this one because once we decide on something we should stick to it. If there's written code it will be tedious work to change it...
It would be helpful to also get the opinion of other library authors that are planning/considering to add typeof support to their libraries. After all, Boost libraries are maintained independently, and, in order to implement any effective policy, we need to reach a consensus. Regards, Arkadiy
Regards,
Tobias
_______________________________________________ Unsubscribe & other changes:

Arkadiy Vertleyb wrote:
"Tobias Schwinger" <tschwinger@neoscientists.org> wrote
Arkadiy Vertleyb wrote:
"Tobias Schwinger" <tschwinger@neoscientists.org> wrote
Why not? I don't understand... If, for example, a Spirit header includes an MPL header, the corresponding Spirit registration header would include the corresponding MPL registration header.
So, if I include the Spirit registration header, I automatically get needed MPL types registered, won't I?
Spirit and MPL are both part of Boost. I was talking about a third party library in between user and Boost code.
In my above statement replace "Spirit" with "third party library". What is going to change?
Spirit knows about Typeof, an arbitrary third party library might not. [...]
It would be helpful to also get the opinion of other library authors that are planning/considering to add typeof support to their libraries. After all, Boost libraries are maintained independently, and, in order to implement any effective policy, we need to reach a consensus.
That would be great. Regards, Tobias

Arkadiy Vertleyb wrote:
"Tobias Schwinger" <tschwinger@neoscientists.org> wrote
Arkadiy Vertleyb wrote:
"Tobias Schwinger" <tschwinger@neoscientists.org> wrote
Why not? I don't understand... If, for example, a Spirit header includes an MPL header, the corresponding Spirit registration header would include the corresponding MPL registration header.
So, if I include the Spirit registration header, I automatically get needed MPL types registered, won't I?
Spirit and MPL are both part of Boost. I was talking about a third party
"Tobias Schwinger" <tschwinger@neoscientists.org> wrote library
in between user and Boost code.
In my above statement replace "Spirit" with "third party library". What is going to change?
Spirit knows about Typeof, an arbitrary third party library might not.
Let's see if I understand correctly... There is a third party library that doesn't know about typeof. This means it doesn't register its types. But it does know about Spirit, and uses it's types in public interface, together with its own types. In this case the third party types need to be registered by the user anyway, but the Spirit types can (or cannot, depending on the approach chosen) be registered in one shot, using the include directory trick, define, etc.. Do you mean something like this? Regards, Arkadiy

Arkadiy Vertleyb wrote:
Let's see if I understand correctly... There is a third party library that doesn't know about typeof. This means it doesn't register its types. But it does know about Spirit, and uses it's types in public interface, together with its own types. In this case the third party types need to be registered by the user anyway, but the Spirit types can (or cannot, depending on the approach chosen) be registered in one shot, using the include directory trick, define, etc..
Do you mean something like this?
Yes (except that the case is pretty unlikely to happen with Spirit in particular -- better examples would be libraries such as Fusion, MPL, Variant...). Regards, Tobias

Arkadiy Vertleyb wrote:
"Tobias Schwinger" <tschwinger@neoscientists.org> wrote
^^^ Sorry, I don't understand this sentence. Would you elaborate, please?
If I have all the types registered in the same header, and if I add a new type, then this registration header needs to be modified to register the new type.
At this point I have to rebuild all the sources that use typeof on _any_ type.
Understood.
Well, I guess we're going to go for #1 then.
Well, I just pointed out a few benefits of #1, but I am by no means sure that it's perfect, and even the best of three...
The benefits you pointed out weren't entirely unimportant ones. From my perspective #1 seems to be the best solution we have so far, because its drawbacks are the least lethal ones. Someone with another, possibly better idea out there?
Where should the header go?
boost/typeof/boost/<LIB>
??
No, definitely not under boost/typeof :-)
I think the registration should be [conceptualy] owned by the library authors rather then typeof library, so I still think boost/<LIB>/typeof is more appropriate. When I was talking about non-intrusiveness I meant files, not directories. It is also much easier to work with CVS when everything is under the same root.
OK -- boost/<LIB>/typeof, then. Regards, Tobias
participants (6)
-
Andy Little
-
Arkadiy Vertleyb
-
dan marsden
-
Joel de Guzman
-
Peder Holt
-
Tobias Schwinger