[enable_if] how to make sure the user supplies the correct number of template arguments

In using enable_if, I came to use a simple technique to detect whether the user is supplying the correct number of (non-Enable) arguments which I think might be useful to add to the enable_if documentation. This addresses the problem which occurs when the user erroneously supplies an extra template argument (that ends up as the Enable template parameter), and it either goes undetected in the compilation or is hard to trace. I get this especially when I decide to reduce the number of template parameters to a class template which uses enable_if. E.g. // ---- WE START WITH template <typename T1, typename T2, typename Enable=void> class enabled_class { // base template implementation }; // user code enabled_class<X, Y> o; but then we change our mind and decide that T1 should not be in the template parameter list for enabled_class: // ----- WE END UP WITH template <typename T2, typename Enable=void> class enabled_class { // base template implementation }; // we forget to change the user code enabled_class<X, Y> o; // this should now be enabled_class<Y> o, but we might not even get an error! The solution I found goes like this: // ---- A PARTIAL SOLUTION template <typename T2, typename Enable=void> class enabled_class { BOOST_MPL_ASSERT((is_same<Enable, void>)); // default implementation }; // we forget to change the user code enabled_class<X, Y> o; // ERROR (except in the unfortunate case when Y is void) Is this a reasonable solution to this problem? Would it be useful to add it to the docs? I suppose this is a problem common to any time default template arguments are used, but I ran into it a lot with enable_if. Having something in the docs that addresses it would have helped me a lot. Stjepan

On Nov 19, 2007 6:12 PM, Stjepan Rajko <stipe@asu.edu> wrote:
// ---- A PARTIAL SOLUTION
template <typename T2, typename Enable=void> class enabled_class { BOOST_MPL_ASSERT((is_same<Enable, void>));
// default implementation };
// we forget to change the user code enabled_class<X, Y> o; // ERROR (except in the unfortunate case when Y is void)
Actually, looks like the void case can be handled as well: namespace detail { struct enable_guard; } template <typename T2, typename Enable=detail::enable_guard> class enabled_class { // Error: Enable has non-default parameter value BOOST_MPL_ASSERT((is_same<Enable, detail::enable_guard>)); // base template implementation... }; template<typename T> class enabled_class< T, typename enable_if< some_condition<T>, detail::enable_guard
::type > { // partial specialization implementation... };
// we forget to change the user code enabled_class<X, Y> o; // ERROR (even if Y is void) Stjepan
participants (1)
-
Stjepan Rajko