From: Dean M. B. <mik...@gm...> - 2007-06-11 13:12:08
|
Hi Everyone, I've only recently been developing with MSVC, and while I've been trying to implement the transformations to the message class I hit a nasty snag. Let me identify what the problem is. First, in boost/network/message/transformers/to_upper.hpp I have the following: struct to_upper_placeholder { template <class Selector> struct type : public impl::to_upper_transformer<Selector> { }; } ; extern to_upper_placeholder to_upper_; I also have in boost/network/message/transformers/selectors.hpp: namespace selectors { struct source_selector { }; struct destination_selector { }; }; // namespace selectors extern selectors::source_selector source_; extern selectors::destination_selector destination_; What I'm concerned about, is that the MSVC linker keeps asking for where to look for these externs when I have the following function template in boost/network/transformers.hpp : template <class Algorithm, class Selector> inline impl::transform_impl<Algorithm, Selector> transform(Algorithm, Selector) { return impl::transform_impl<Algorithm, Selector>(); }; This is used in the unit test (which fails to compile in MSVC 8) libs/network/test/message_transform_test.cpp : using namespace boost::network; message msg; msg << source("me"); BOOST_CHECK_EQUAL ( source(msg), "me" ); msg << transform(to_upper_, source_); BOOST_CHECK_EQUAL ( source(msg), "ME" ); Clearly, the 'transform' template method only requires the type information of to_upper_ (an extern to_upper_placeholder) and source_ (an extern selectors::source_selector) but MSVC seems to require that they be linkable from somewhere. Any thoughts on the matter? I haven't tried this in GCC yet, but I'm confident that GCC would know that I don't really need to link to these instances -- that I just need the type to be deduced in the 'transform' template and not care about the actual instances. Help and insight would be most appreciated. Thanks and hope to hear from any one of you soon! (Please update to Revision 17 to get the latest unit tests and implementations from trunk/) -- Dean Michael C. Berris http://cplusplus-soup.blogspot.com/ mikhailberis AT gmail DOT com +63 928 7291459 |
From: Christian H. <chh...@gm...> - 2007-06-11 14:47:59
|
Dean, if you remove the extern specifier it compiles fine on my machine. I'm using MSVC 7.1. Why did you decided to implement it this way? Is it possible to just typedef this information? Thanks, Christian On 6/11/07, Dean Michael Berris <mik...@gm...> wrote: > Hi Everyone, > > I've only recently been developing with MSVC, and while I've been > trying to implement the transformations to the message class I hit a > nasty snag. Let me identify what the problem is. > > First, in boost/network/message/transformers/to_upper.hpp I have the following: > > struct to_upper_placeholder { > template <class Selector> > struct type : public impl::to_upper_transformer<Selector> { }; > } ; > > extern to_upper_placeholder to_upper_; > > I also have in boost/network/message/transformers/selectors.hpp: > > namespace selectors { > struct source_selector { }; > struct destination_selector { }; > }; // namespace selectors > > extern selectors::source_selector source_; > extern selectors::destination_selector destination_; > > What I'm concerned about, is that the MSVC linker keeps asking for > where to look for these externs when I have the following function > template in boost/network/transformers.hpp : > > > template <class Algorithm, class Selector> > inline impl::transform_impl<Algorithm, Selector> > transform(Algorithm, Selector) { > return impl::transform_impl<Algorithm, Selector>(); > }; > > This is used in the unit test (which fails to compile in MSVC 8) > libs/network/test/message_transform_test.cpp : > > using namespace boost::network; > > message msg; > msg << source("me"); > BOOST_CHECK_EQUAL ( source(msg), "me" ); > msg << transform(to_upper_, source_); > BOOST_CHECK_EQUAL ( source(msg), "ME" ); > > Clearly, the 'transform' template method only requires the type > information of to_upper_ (an extern to_upper_placeholder) and source_ > (an extern selectors::source_selector) but MSVC seems to require that > they be linkable from somewhere. > > Any thoughts on the matter? I haven't tried this in GCC yet, but I'm > confident that GCC would know that I don't really need to link to > these instances -- that I just need the type to be deduced in the > 'transform' template and not care about the actual instances. > > Help and insight would be most appreciated. > > Thanks and hope to hear from any one of you soon! > > (Please update to Revision 17 to get the latest unit tests and > implementations from trunk/) > > -- > Dean Michael C. Berris > http://cplusplus-soup.blogspot.com/ > mikhailberis AT gmail DOT com > +63 928 7291459 > > ------------------------------------------------------------------------- > This SF.net email is sponsored by DB2 Express > Download DB2 Express C - the FREE version of DB2 express and take > control of your XML. No limits. Just data. Click to get it now. > http://sourceforge.net/powerbar/db2/ > _______________________________________________ > Cpp-netlib-devel mailing list > Cpp...@li... > https://lists.sourceforge.net/lists/listinfo/cpp-netlib-devel > |
From: Christian H. <chh...@gm...> - 2007-06-11 14:59:32
|
Dean, I just put a typedef on front of: typedef to_upper_placeholder to_upper_; typedef selectors::source_selector source_; typedef selectors::destination_selector destination_; I changed the test code to: msg << transform(to_upper_(), source_()); And there were no problems. Does that makes sense to you? Christian On 6/11/07, Christian Henning <chh...@gm...> wrote: > Dean, if you remove the extern specifier it compiles fine on my > machine. I'm using MSVC 7.1. Why did you decided to implement it this > way? Is it possible to just typedef this information? > > Thanks, > Christian > > > > On 6/11/07, Dean Michael Berris <mik...@gm...> wrote: > > Hi Everyone, > > > > I've only recently been developing with MSVC, and while I've been > > trying to implement the transformations to the message class I hit a > > nasty snag. Let me identify what the problem is. > > > > First, in boost/network/message/transformers/to_upper.hpp I have the following: > > > > struct to_upper_placeholder { > > template <class Selector> > > struct type : public impl::to_upper_transformer<Selector> { }; > > } ; > > > > extern to_upper_placeholder to_upper_; > > > > I also have in boost/network/message/transformers/selectors.hpp: > > > > namespace selectors { > > struct source_selector { }; > > struct destination_selector { }; > > }; // namespace selectors > > > > extern selectors::source_selector source_; > > extern selectors::destination_selector destination_; > > > > What I'm concerned about, is that the MSVC linker keeps asking for > > where to look for these externs when I have the following function > > template in boost/network/transformers.hpp : > > > > > > template <class Algorithm, class Selector> > > inline impl::transform_impl<Algorithm, Selector> > > transform(Algorithm, Selector) { > > return impl::transform_impl<Algorithm, Selector>(); > > }; > > > > This is used in the unit test (which fails to compile in MSVC 8) > > libs/network/test/message_transform_test.cpp : > > > > using namespace boost::network; > > > > message msg; > > msg << source("me"); > > BOOST_CHECK_EQUAL ( source(msg), "me" ); > > msg << transform(to_upper_, source_); > > BOOST_CHECK_EQUAL ( source(msg), "ME" ); > > > > Clearly, the 'transform' template method only requires the type > > information of to_upper_ (an extern to_upper_placeholder) and source_ > > (an extern selectors::source_selector) but MSVC seems to require that > > they be linkable from somewhere. > > > > Any thoughts on the matter? I haven't tried this in GCC yet, but I'm > > confident that GCC would know that I don't really need to link to > > these instances -- that I just need the type to be deduced in the > > 'transform' template and not care about the actual instances. > > > > Help and insight would be most appreciated. > > > > Thanks and hope to hear from any one of you soon! > > > > (Please update to Revision 17 to get the latest unit tests and > > implementations from trunk/) > > > > -- > > Dean Michael C. Berris > > http://cplusplus-soup.blogspot.com/ > > mikhailberis AT gmail DOT com > > +63 928 7291459 > > > > ------------------------------------------------------------------------- > > This SF.net email is sponsored by DB2 Express > > Download DB2 Express C - the FREE version of DB2 express and take > > control of your XML. No limits. Just data. Click to get it now. > > http://sourceforge.net/powerbar/db2/ > > _______________________________________________ > > Cpp-netlib-devel mailing list > > Cpp...@li... > > https://lists.sourceforge.net/lists/listinfo/cpp-netlib-devel > > > |
From: Dean M. B. <mik...@gm...> - 2007-06-11 16:30:09
|
Hi Christian, On 6/11/07, Christian Henning <chh...@gm...> wrote: > > And there were no problems. Does that makes sense to you? > Two issues here: 1. The unit test is a specification on how the interface is meant to be. Although your solution would work, the readability of additional parentheses aren't very appealing to me. The unit test is an example in itself of how the interface *should* look like and I'd like to_upper_ (and other future transformations to be implemented) to not have the extra parentheses. msg << transform(to_upper_, source_) ; Reads better IMO than msg << transform(to_upper_(), source_()) ; The same way boost::bind(&function, _1) ; Reads better than boost::bind(&function, _1()) ; 2. The premium is put on readability and extensibility. The transform template function is meant to extend to more than just a pair of parameters. For flexibility's sake, see the example below: msg << transform(to_upper_, source_ & destination_) << transform(headers_, to_upper_ & trim_) ; With template metaprogramming, operator& can be overloaded to produce a composite selector and composite transformations. This gives 'transform' a flexible enough interface which allows: msg << transform(to_upper_, source_) << transform(source_, to_upper_) ; Of course, with the help of template metaprogramming. In this regard, having extra parentheses doesn't help with readability. NOTE: This is the direction of the transformation interface (and other interfaces to the message type in general), to leverage on compile-time meta-programming to produce readable and flexible interfaces. The above are the two rationale's for why I opted for 'extern to_upper_placeholder to_upper_' instead of making it a typedef in the first place. It just so happened that my first iteration implementation hit a snag (which I sure hope would be temporary). So the real question now would be (assuming it works with GCC) how we can allow the above parentheses-less while keeping MSVC and other compilers happy? -- Dean Michael C. Berris http://cplusplus-soup.blogspot.com/ mikhailberis AT gmail DOT com +63 928 7291459 |
From: Christian H. <chh...@gm...> - 2007-06-11 17:38:19
|
Hi Dean, I think the MS compiler is right. Defining a variable extern means it has external linkage. We shouldn't try to be "too smart" in fooling the compiler. This code can break with every new compiler version. I don't see it as a problem when using parenthesis. boost::gil does something similar channel_t& c = get_color( pixel, red_t() ); But if you don't like that then there are other ways, like using an enum ( I know it's old school ) or use total template specialization. I'm sure there are other ways. Christian On 6/11/07, Dean Michael Berris <mik...@gm...> wrote: > Hi Christian, > > On 6/11/07, Christian Henning <chh...@gm...> wrote: > > > > And there were no problems. Does that makes sense to you? > > > > Two issues here: > > 1. The unit test is a specification on how the interface is meant to > be. Although your solution would work, the readability of additional > parentheses aren't very appealing to me. The unit test is an example > in itself of how the interface *should* look like and I'd like > to_upper_ (and other future transformations to be implemented) to not > have the extra parentheses. > > msg << transform(to_upper_, source_) ; > > Reads better IMO than > > msg << transform(to_upper_(), source_()) ; > > The same way > > boost::bind(&function, _1) ; > > Reads better than > > boost::bind(&function, _1()) ; > > 2. The premium is put on readability and extensibility. The transform > template function is meant to extend to more than just a pair of > parameters. For flexibility's sake, see the example below: > > msg << transform(to_upper_, source_ & destination_) > << transform(headers_, to_upper_ & trim_) > ; > > With template metaprogramming, operator& can be overloaded to produce > a composite selector and composite transformations. This gives > 'transform' a flexible enough interface which allows: > > msg << transform(to_upper_, source_) << transform(source_, to_upper_) ; > > Of course, with the help of template metaprogramming. In this regard, > having extra parentheses doesn't help with readability. > > NOTE: This is the direction of the transformation interface (and other > interfaces to the message type in general), to leverage on > compile-time meta-programming to produce readable and flexible > interfaces. > > The above are the two rationale's for why I opted for 'extern > to_upper_placeholder to_upper_' instead of making it a typedef in the > first place. It just so happened that my first iteration > implementation hit a snag (which I sure hope would be temporary). > > So the real question now would be (assuming it works with GCC) how we > can allow the above parentheses-less while keeping MSVC and other > compilers happy? > > -- > Dean Michael C. Berris > http://cplusplus-soup.blogspot.com/ > mikhailberis AT gmail DOT com > +63 928 7291459 > > ------------------------------------------------------------------------- > This SF.net email is sponsored by DB2 Express > Download DB2 Express C - the FREE version of DB2 express and take > control of your XML. No limits. Just data. Click to get it now. > http://sourceforge.net/powerbar/db2/ > _______________________________________________ > Cpp-netlib-devel mailing list > Cpp...@li... > https://lists.sourceforge.net/lists/listinfo/cpp-netlib-devel > |
From: Dean M. B. <mik...@gm...> - 2007-06-12 01:24:50
|
Hi Christian, On 6/11/07, Christian Henning <chh...@gm...> wrote: > Hi Dean, I think the MS compiler is right. Defining a variable extern > means it has external linkage. We shouldn't try to be "too smart" in > fooling the compiler. This code can break with every new compiler > version. > Although it does make sense that extern will cause for compilation/linking to require that the object be allocated somewhere, if you check the code again for the transform template method, it doesn't use the extern variables. template <class Algorithm, class Selector> inline impl::transform_impl<Algorithm, Selector> transform(Algorithm, Selector) { return impl::transform_impl<Algorithm, Selector>(); }; That means, when transform(to_header_, source_) is called, nothing should require linkage to to_header_ and source_ since transform(...) doesn't use it (but the type information) anywhere. > I don't see it as a problem when using parenthesis. boost::gil does > something similar > > channel_t& c = get_color( pixel, red_t() ); > True, but this doesn't scale well when we start implementing stuff like operator&, operator|, and other operator overloads. > But if you don't like that then there are other ways, like using an > enum ( I know it's old school ) or use total template specialization. > I'm sure there are other ways. > Total template specialization doesn't make sense yet, especially if there's no _easy_ way of invoking transform(...) with placeholders. Enums are out of the question. ;-) I guess what I'm really looking for is how boost::bind's _1, _2, _N works... :-D -- Dean Michael C. Berris http://cplusplus-soup.blogspot.com/ mikhailberis AT gmail DOT com +63 928 7291459 |