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)

boost-1.54.0-mpl-print.patch (833 bytes ) - added by pmachata@… 9 years ago.
Fix mpl::print in GCC

Download all attachments as: .zip

Change History (13)

comment:1 by Robert Ramey, 11 years ago

Managed to make it work for my GCC system as well !

template <class T>
struct print
    : mpl::identity<T *>
#if defined(__MWERKS__)
    , aux::print_base
#endif 
{
#if defined(BOOST_MSVC)
    enum { n = sizeof(T) + -1 };
#elif defined(__MWERKS__)
    void f(int);
#else 
    enum {
        n =
# if defined(__EDG_VERSION__)
           aux::dependent_unsigned<T>::value > -1
# else 
           sizeof(T) / 0//sizeof(T) > -1
# endif 
        };
#endif 
};

Robert Ramey

comment:2 by Robert Ramey, 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

in reply to:  description comment:3 by Dave Abrahams, 11 years ago

Resolution: invalid
Status: newclosed

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.

in reply to:  2 comment:4 by Dave Abrahams, 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 pmachata@…, 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:6 by pmachata@…, 9 years ago

... alternatively, I suppose, there could be both.

comment:7 by pmachata@…, 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 pmachata@…, 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.

by pmachata@…, 9 years ago

Fix mpl::print in GCC

comment:9 by Dave Abrahams, 9 years ago

Resolution: invalid
Status: closedreopened

comment:10 by Dave Abrahams, 9 years ago

Owner: changed from Dave Abrahams to Aleksey Gurtovoy
Status: reopenednew

comment:11 by Jonathan Wakely <jwakely.boost@…>, 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.

comment:12 by Jonathan Wakely <jwakely.boost@…>, 7 years ago

It stopped working with GCC 4.8

Note: See TracTickets for help on using tickets.