Bug 43608 - Boost.MPL code doesn't get the placeholders substituted anymore
Summary: Boost.MPL code doesn't get the placeholders substituted anymore
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.5.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
: 43775 (view as bug list)
Depends on:
Blocks:
 
Reported: 2010-03-31 20:18 UTC by Philipp
Modified: 2010-04-18 15:04 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments
reduced testcase (593 bytes, text/plain)
2010-04-01 10:49 UTC, Jonathan Wakely
Details
reduced testcase with fix added but commented out (603 bytes, text/plain)
2010-04-01 11:10 UTC, Jonathan Wakely
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Philipp 2010-03-31 20:18:01 UTC
The following code stopped working with gcc-4.5.
gcc-4.4.3 and clang both accept it.
On gcc-4.5, boost::mpl_::arg<2> is passed to metafunction instead of test1.
The strange thing is: If the specialization of metafunction<_2> is provided, the code works again.
I'm sorry that this is not a minimal test case, because I don't know how to get rid of the MPL parts.


#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/fold.hpp>
#include <boost/mpl/push_back.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/vector/vector10.hpp>

struct test1
{
        typedef int inner_type;
};

template<
        typename Foo
>
struct metafunction
{
        typedef typename Foo::inner_type type;
};

#if 0
template<>
struct metafunction<
        boost::mpl::_2
>;
#endif

int main()
{
        typedef boost::mpl::fold<
                boost::mpl::vector1<
                        test1
                >,
                boost::mpl::vector0<>,
                boost::mpl::push_back<
                        boost::mpl::_1,
                        metafunction<
                                boost::mpl::_2
                        >
                >
        >::type transformed;

        boost::mpl::at_c<transformed, 0>::type i = 42;
}
Comment 1 Jonathan Wakely 2010-04-01 10:49:06 UTC
Created attachment 20271 [details]
reduced testcase

reduced to just the instantiation that fails with 4.5
Comment 2 Jonathan Wakely 2010-04-01 10:53:04 UTC
the subject line is misleading, I think the placeholders are still substituted in exactly the same way, but as part of that an invalid instantiation is generated while determining the template_arity of the metafunction.

The invalid instantiation occurs in a sizeof expression and was previously ignored (presumably due to SFINAE) but now causes an error.  I don't think SFINAE applies in that context, which would make 4.5 correct
Comment 3 Jonathan Wakely 2010-04-01 11:10:19 UTC
Created attachment 20272 [details]
reduced testcase with fix added but commented out

Comeau's online compiler agrees with GCC 4.5

As the reporter says, the testcase can be fixed by adding an explicit specialisation of metafunction< arg<2> > ... I don't know why this works.

The second attachment has the specialisation, commented out.
Comment 4 Richard Biener 2010-04-01 13:56:39 UTC
EDG accepts the reduced testcase in strict mode.
Comment 5 Jason Merrill 2010-04-01 14:47:22 UTC
My copy of EDG 4.1 does not accept the reduced testcase; it gives the same error as GCC 4.5.

"red.cc", line 111: error: class "arg<2>" has no member "inner_type"
          typedef typename Foo::inner_type type;
                                ^
          detected during:
            instantiation of class "metafunction<Foo> [with Foo=arg<2>]" at
                      line 83
            instantiation of class "template_arity_impl<F, N> [with
                      F=metafunction<arg<2>>, N=1]" at line 91
            instantiation of class
                      "template_arity<F> [with F=metafunction<arg<2>>]" at
                      line 116

We instantiate metafunction<arg<2>> for argument-dependent lookup of the call to arity_helper(type_wrapper<F>).  3.4.2 says that if an argument type is a class template specialization, we consider the associated classes and namespaces of the template arguments, which in this case means F, or metafunction<arg<2>>.  And in order to perform that lookup, we instantiate metafunction<arg<2>>.

Providing the explicit specialization prevents the implicit instantiation, so argument-dependent lookup just doesn't consider that scope.  This is also fully conformant.
Comment 6 Jason Merrill 2010-04-01 14:59:50 UTC
Another way to fix the testcase would be to give an explicit scope for arity_helper, so argument-dependent lookup isn't needed.
Comment 7 Philipp 2010-04-01 15:21:52 UTC
Thank you all very much. Explicitly scoping arity_helper indeed fixes the issue.
Comment 8 Jason Merrill 2010-04-18 15:04:13 UTC
*** Bug 43775 has been marked as a duplicate of this bug. ***