Opened 11 years ago
Last modified 7 years ago
#5637 new Tasks
use of mpl::print imposes default constructible requirement on argument
Reported by: | Robert Ramey | Owned by: | Aleksey Gurtovoy |
---|---|---|---|
Milestone: | To Be Determined | Component: | mpl |
Version: | Boost 1.46.1 | Severity: | Problem |
Keywords: | mpl print | Cc: |
Description
I'm using the following to debug some TMP code that looks like the following.
#include <boost/mpl/print.hpp> struct X { X(int); }; boost::mpl::print< X >::type x; boost::mpl::print< X >::type y;
I get an error message that the type X is not default constructible. A little investigation yields the definition of mpl::print (simplified for exposition)
template <class T> struct print : identity<T> { enum { n = sizeof(T) + -1 }; };
So invoking the print creates an instance with the default constructor which provokes the error in this case. For my purposes, I made the following change which seems to address the problem:
template <class T> struct print : identity<T *> { enum { n = sizeof(T) + -1 }; };
I'm using MSVC 9.0.
A couple of misceleanous issues besides this:
On my current version of GCC - 4.3.4 I get no warning at all.
If the same type is printed more than once, I only get the warning on the first instance.
Robert Ramey
Attachments (1)
Change History (13)
comment:1 by , 11 years ago
follow-up: 4 comment:2 by , 11 years ago
Damn - my patch mpl::identity<T> <- mpl::identity<T *> - broke type printing of reference types. So I withdraw that suggestion. The other change:sizeof(T) > -1 <- sizeof(T) / 0 still stands however - at least from my version of GCC.
Robert Ramey
comment:3 by , 11 years ago
Resolution: | → invalid |
---|---|
Status: | new → closed |
Replying to ramey:
I'm using the following to debug some TMP code that looks like the following.
#include <boost/mpl/print.hpp> struct X { X(int); }; boost::mpl::print< X >::type x; boost::mpl::print< X >::type y;I get an error message that the type X is not default constructible.
I don't think mpl::print is supposed to guarantee you can do that. Why don't you just do
boost::mpl::print<X> y;
instead?
A little investigation yields the definition of mpl::print (simplified for exposition)
template <class T> struct print : identity<T> { enum { n = sizeof(T) + -1 }; };So invoking the print creates an instance with the default constructor
No. Even if you treat mpl::print
as a metafunction, invoking it doesn't create an instance. Constructing an instance of its result… creates an an instance (which is of course tautological, sorry).
which provokes the error in this case. For my purposes, I made the following change which seems to address the problem:
template <class T> struct print : identity<T *> { enum { n = sizeof(T) + -1 }; };I'm using MSVC 9.0.
Unfortunately, mpl::print
is undocumented, but the intention is that as a metafunction, it returns T
, not T*
, so that change wouldn't work.
A couple of misceleanous issues besides this:
On my current version of GCC - 4.3.4 I get no warning at all.
If you can figure out how to generate an appropriate warning for that compiler, we'd love to have a patch.
If the same type is printed more than once, I only get the warning on the first instance.
Nothing we can do about the latter; it's just an artifact of your compiler's behavior.
comment:4 by , 11 years ago
Replying to ramey:
The other change:sizeof(T) > -1 <- sizeof(T) / 0 still stands however - at least from my version of GCC.
As far as I know, division by zero is still a hard error. mpl::print
is supposed to generate warnings. If you're satisfied with an error, I'm sure you can figure out how to do that without using print
.
comment:5 by , 9 years ago
It seems that using NULL to initialize the enum value tickles GCC the right way to produce a warning if the template is actually used (unlike division by zero, which produces one warning always, and optionally more warnings if print is actually "invoked"). It's also enabled by default, unlike signed/unsigned compare that's used in the current solution.
One downside is that we get a warning only for the first failure in a translation unit. What's considered more important: that we have one warning always, or that we get all citations, but only with -Wall?
comment:7 by , 9 years ago
Apologies, I was interpreting the output wrong. Initialization by NULL appears to do exactly what we need.
From what I can figure out from GCC sources, this warning is controlled by -Wconversion-null, which has been on by default since it was introduced in 2010 (4.5.0). Before that, the warning was emitted as well, keyed to -Wconversion, which was off even in -Wall. From the time it was written in 2000 until 2006 (4.1.0), the warning was always emitted and couldn't even be turned off. So after 4.1.0 up until 4.5.0, it's more advantageous to use the signed/unsigned comparison (which is on at least in -Wall), otherwise the NULL conversion is better.
comment:8 by , 9 years ago
Comparison of values belonging to different enums is even better. That appears to be available since 1996, and is bound to always-on -Wenum-compare since 2008.
comment:9 by , 9 years ago
Resolution: | invalid |
---|---|
Status: | closed → reopened |
comment:10 by , 9 years ago
Owner: | changed from | to
---|---|
Status: | reopened → new |
comment:11 by , 7 years ago
Hmm, the GCC patch no longer seems to work, or I just can't figure out what mpl::print is meant to do.
Managed to make it work for my GCC system as well !
Robert Ramey