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; }
Created attachment 20271 [details] reduced testcase reduced to just the instantiation that fails with 4.5
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
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.
EDG accepts the reduced testcase in strict mode.
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.
Another way to fix the testcase would be to give an explicit scope for arity_helper, so argument-dependent lookup isn't needed.
Thank you all very much. Explicitly scoping arity_helper indeed fixes the issue.
*** Bug 43775 has been marked as a duplicate of this bug. ***