Re:Re: [boost] [serialization] export macros

Christoph Ludwig wrote:
template<class> struct pack;
template<class T> struct pack<void (T)> { typedef T type; };
BOOST_CLASS_EXPORT( pack<void (DerivedStatus< Algo<int, double >
)>::type );
That did the trick! Great!
I am not sure which of Boost's libraries is the most adequate place for such a tool (preprocessor? mpl?), but it is certainly valuable. And if / once there is such a tool in Boost, then the documentation of macros that are likely to take classes genareted from templates as arguments should refer to it.
Hmmm - maybe we should just roll this into export.hpp - Would this create any other problems? Robert Ramey

Hi, On Sun, Aug 08, 2004 at 11:38:15AM -0700, Robert Ramey wrote:
Christoph Ludwig wrote:
template<class> struct pack;
template<class T> struct pack<void (T)> { typedef T type; };
BOOST_CLASS_EXPORT( pack<void (DerivedStatus< Algo<int, double >
)>::type );
That did the trick! Great!
I am not sure which of Boost's libraries is the most adequate place for such a tool (preprocessor? mpl?), but it is certainly valuable. And if / once there is such a tool in Boost, then the documentation of macros that are likely to take classes genareted from templates as arguments should refer to it.
Hmmm - maybe we should just roll this into export.hpp - Would this create any other problems?
I don't see how it could interfere with other libraries if it is defined in namespace serialization. The only limitation of this technique I am aware right now is that you almost always need to use BOOST_CLASS_EXPORT_GUID; the implied guid of BOOST_CLASS_EXPORT is even in the case of short class template names and short arguments often longer than the limit of 127 characters. (But then I am testing this technique only since today and I am still hunting bugs in my program probably unrelated to the export issue. If there are problems I may very well not have encountered them yet.) However, this problem is by no means specific to the serialization library. Whenever you have a macro that takes a classname you may face this issue. One could consider it a (inherent) preprocessor shortcoming solved by means of template programming. Therefore the preprocessor library or one of the libraries from Boost's Generic Programming and Template Metaprogramming sections seem a more natural place to me for such a tool. Of course, I don't know if one of the authors of these libraries agrees and plans to eventually include such a template. Since the next release is (hopefully) not long away I'd only mention this workaround in the documentation of the export macros. Once the release is out and everything has settled down there's time to discuss where this template belongs. This template requires so few keystrokes that for the time being the users that need it can easily provide it themselves. But in order to avoid unnecessary bloat of Boost I wouldn't like to see it duplicated in several Boost libraries in the end. Regards Christoph -- http://www.informatik.tu-darmstadt.de/TI/Mitarbeiter/cludwig.html LiDIA: http://www.informatik.tu-darmstadt.de/TI/LiDIA/Welcome.html

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Christoph Ludwig
However, this problem is by no means specific to the serialization library.
No, it isn't. Note also that the solution is incomplete. Types have to not only be capable of being argument types (e.g. not 'void'), but they also must remain unchanged by simply being an argument type (e.g. array declarations decay to pointers, function types are transformed to pointer to function types). In other words, the solution only works for the common case.
Whenever you have a macro that takes a classname you may face this issue. One could consider it a (inherent) preprocessor shortcoming solved by means of template programming.
As an aside, if you have a conforming preprocessor, the problem is solveable with the preprocessor (especially so with variadics). Regards, Paul Mensonides

On Fri, Aug 13, 2004 at 07:17:33PM -0700, Paul Mensonides wrote:
From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Christoph Ludwig
However, this problem is by no means specific to the serialization library.
No, it isn't.
Note also that the solution is incomplete. Types have to not only be capable of being argument types (e.g. not 'void'), but they also must remain unchanged by simply being an argument type (e.g. array declarations decay to pointers, function types are transformed to pointer to function types). In other words, the solution only works for the common case.
Just for clarification: You say that in the following template<class> struct pack; template<class T> struct<void (T)> { typedef T type; }; MY_MACRO(pack<void (void)>::type) MY_MACRO(pack<void (MyTemplate<int, int>[10])>::type) both macro expansions won't work (or more precisely, result in code that will fail or yield unwanted results when compiled)? Hm, I probably should peruse my copy of the book by Vandvoorde and Josuttis again, but this makes kind of sense. IIUC this might be a problem if you need to be able to pass *any* type to a macro. But in the case of the serialization lib it's always a class type that needs to be registered. And neither void nor MyTemplate<int, int>[10] is a class type. Are you aware of any examples where above approach won't work when calling the serialization lib's export macros?
Whenever you have a macro that takes a classname you may face this issue. One could consider it a (inherent) preprocessor shortcoming solved by means of template programming.
As an aside, if you have a conforming preprocessor, the problem is solveable with the preprocessor (especially so with variadics).
Is it solveable with the preprocessor as defined in the C++ standard from 1998? Or do you need the C99 preprocessor? Regards Christoph -- http://www.informatik.tu-darmstadt.de/TI/Mitarbeiter/cludwig.html LiDIA: http://www.informatik.tu-darmstadt.de/TI/LiDIA/Welcome.html

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Christoph Ludwig
Just for clarification: You say that in the following
template<class> struct pack;
template<class T> struct<void (T)> { typedef T type; };
MY_MACRO(pack<void (void)>::type) MY_MACRO(pack<void (MyTemplate<int, int>[10])>::type)
both macro expansions won't work (or more precisely, result in code that will fail or yield unwanted results when compiled)? Hm, I probably should peruse my copy of the book by Vandvoorde and Josuttis again, but this makes kind of sense.
Yes, 'void (void)' is a valid function type, but it is the same as 'void ()' which won't match the partial specialization (though that could be made to work, but it isn't worth it). The following two function types are identical because array types decay to pointers when used as parameter types. void (MyTemplate<int, int>[10]) void (MyTemplate<int, int>*) Similar thing for: void (int (int)) void (int (*)(int)) because function types used as parameter types transform to pointers to function types. I suppose another way to do it would be: template<class T> struct id { typedef T type; }; template<class> struct pack; template<class T> struct pack<void (id<T>)> : id<T> { }; MY_MACRO(pack<void (id<void>)>::type) MY_MACRO(pack<void (id<MyTemplate<int, int>[10]>)>::type) But an even better way is to do the unpacking in the macro and clean up the syntax: struct pack; template<class T> struct lock { typedef T type; }; template<class T> struct unpack : lock<T> { }; template<> struct unpack<pack (void)> : lock<void> { }; template<class T> struct unpack<pack (T)> : lock<T> { }; template<class T> struct unpack<pack (lock<T>)> : lock<T> { }; #define MY_MACRO(t) ... unpack<t>::type ... MY_MACRO( int ) MY_MACRO( pack (std::pair<int, int>) ) MY_MACRO( pack (lock<int[10]>) )
IIUC this might be a problem if you need to be able to pass *any* type to a macro. But in the case of the serialization lib it's always a class type that needs to be registered. And neither void nor MyTemplate<int, int>[10] is a class type. Are you aware of any examples where above approach won't work when calling the serialization lib's export macros?
No, I was referring to the general problem.
Whenever you have a macro that takes a classname you may face this issue. One could consider it a (inherent) preprocessor shortcoming solved by means of template programming.
As an aside, if you have a conforming preprocessor, the problem is solveable with the preprocessor (especially so with variadics).
Is it solveable with the preprocessor as defined in the C++ standard from 1998? Or do you need the C99 preprocessor?
It is solveable in C++ (though it is "prettier" in C99). Either way, it isn't an option because it requires a very very conformant preprocessor. Regards, Paul Mensonides

On Sat, Aug 14, 2004 at 10:57:36AM -0700, Paul Mensonides wrote:
I suppose another way to do it would be:
template<class T> struct id { typedef T type; };
template<class> struct pack; template<class T> struct pack<void (id<T>)> : id<T> { };
MY_MACRO(pack<void (id<void>)>::type) MY_MACRO(pack<void (id<MyTemplate<int, int>[10]>)>::type)
But an even better way is to do the unpacking in the macro and clean up the syntax:
struct pack;
template<class T> struct lock { typedef T type; };
template<class T> struct unpack : lock<T> { }; template<> struct unpack<pack (void)> : lock<void> { }; template<class T> struct unpack<pack (T)> : lock<T> { }; template<class T> struct unpack<pack (lock<T>)> : lock<T> { };
#define MY_MACRO(t) ... unpack<t>::type ...
MY_MACRO( int ) MY_MACRO( pack (std::pair<int, int>) ) MY_MACRO( pack (lock<int[10]>) )
Wow. I am always surprised what you can achieve with some template metaprogramming. And I consider your example particularly elegant because a user can ignore the machinery unless the naive approach fails. Very neat! Thanks for writing it down! Regards Christoph -- http://www.informatik.tu-darmstadt.de/TI/Mitarbeiter/cludwig.html LiDIA: http://www.informatik.tu-darmstadt.de/TI/LiDIA/Welcome.html

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Christoph Ludwig
Wow. I am always surprised what you can achieve with some template metaprogramming. And I consider your example particularly elegant because a user can ignore the machinery unless the naive approach fails. Very neat!
Note, BTW, that unpacking the type inside the macro introduces a dependency with 'typename' if the resulting type is dependent.
Thanks for writing it down!
You're welcome. Regards, Paul Mensonides
participants (3)
-
Christoph Ludwig
-
Paul Mensonides
-
Robert Ramey