[boost::mpl::apply] compiler dependent behavior
Hi, I'm currently using the apply metafunction, and I have two different behaviors depending on the used compiler. Here is the code : #include <boost/mpl/lambda.hpp> #include <boost/mpl/apply.hpp> #include <boost/mpl/placeholders.hpp> #include <tr1/unordered_set> using namespace boost; using namespace mpl; int main () { apply < std::tr1::unordered_set < _1 , std::equal_to < int>, std::tr1::hash <int>, std::allocator < int > >, int > ::type foo; } With g++ 4.1, there is no error. With g++ 4.2, icc 9.1, an error occurs: - g++ : no class template named 'apply' in 'class std::tr1::unordered_set<mpl_::arg<1>, std::equal_to<int>, std::tr1::hash<int>, std::allocator<int>, false>' - icc: class "std::tr1::unordered_set<boost::mpl::_1, std::equal_to<int>, std::tr1::hash<int>, std::allocator<int>, false>" has no member class "apply" : F::template apply<T1> With g++ 4.3, on some computers, it works, on others it does not. Can you give me some help to make this work ? Thanks, -- Samuel
Samuel Charron wrote:
Hi,
I'm currently using the apply metafunction, and I have two different behaviors depending on the used compiler.
<snip code>
With g++ 4.1, there is no error. With g++ 4.2, icc 9.1, an error occurs:
I can't verify, but I believe it's might be:
- g++ : no class template named 'apply' in 'class std::tr1::unordered_set<mpl_::arg<1>, std::equal_to<int>, std::tr1::hash<int>, std::allocator<int>, false>' ^^^^^^
Placeholder substitution won't work in argument lists of templates with non-type parameters (well, sometimes it does work, but only if there is a default and if the compiler deduces template template arguments in a certain, probably non-standard way).
Can you give me some help to make this work ?
To work around this limitation, you can use a custom Metafunction template<typename T> struct specialize_unordered_set { typedef std::tr1:unordered_set<T> type; }; and then use it in a Placeholder Expression. Alternatively (this way might save you some compile time), you can write a Metafunction Class to replace the Placeholder Expression: struct specialize_unordered_set { template<typename T> struct apply { typedef std::tr1::unordered_set<T> type; }; }; HTH. Regards, Tobias
Hi,
I'm currently using the apply metafunction, and I have two different behaviors depending on the used compiler.
<snip code>
With g++ 4.1, there is no error. With g++ 4.2, icc 9.1, an error occurs:
I can't verify, but I believe it's might be:
- g++ : no class template named 'apply' in 'class std::tr1::unordered_set<mpl_::arg<1>, std::equal_to<int>, std::tr1::hash<int>, std::allocator<int>, false>' ^^^^^^
Placeholder substitution won't work in argument lists of templates with non-type parameters (well, sometimes it does work, but only if there is a default and if the compiler deduces template template arguments in a certain, probably non-standard way).
Can you give me some help to make this work ?
To work around this limitation, you can use a custom Metafunction
template<typename T> struct specialize_unordered_set { typedef std::tr1:unordered_set<T> type; };
and then use it in a Placeholder Expression. Alternatively (this way might save you some compile time), you can write a Metafunction Class to replace the Placeholder Expression:
struct specialize_unordered_set { template<typename T> struct apply { typedef std::tr1::unordered_set<T> type; }; };
Working on this bug this afternoon, I found what I think is a cause to that bug. It comes from template_arity. It returns -1 with buggy compilers and the right numbers of parameters with working compilers. The issue comes from non-type parameters in a template with default values. An example of a code with different behaviours : # include <boost/mpl/aux_/template_arity.hpp> # include <iostream> template < typename A, bool t = false> struct foo { }; int main() { std::cout << boost::mpl::aux::template_arity < foo < int > > ::type::value << std::endl; } Here, with a template < template < class > >, the match works with some compilers, while others consider that the bool must be part of the template template expression. To make this work, I finally wrapped my class with a templated structure typedef'ing the unordered_set < template_parameters > as ::type. The apply metafunction did the necessary automagically, without defining an apply structure. -- Samuel
participants (2)
-
Samuel Charron
-
Tobias Schwinger