Can I model default template arguments in partial specializations?

The default template arguments can be used to model aliases for complex type expressions in a template declaration. For instance:

template <typename X,
          typename Y = do_something_with<X>::type,
          typename Z = some_other_thing_using<X, Y>::type
struct foo { ... X, Y, Z ... };

However, partial specializations may not have default template arguments ( [C++11: 14.5.5/8]), so this trick does not work. You may ask yourself why the typedef in the body will not work, and the answer is that aliases must be in scope before the class body in order to make a conditional inclusion; eg:.

template <typename T, typename Enable = void>
struct bar;

// Wishful thinking:
template <typename X,
          typename Y = do_something_with<X>::type,
          typename Z = some_other_thing_using<X, Y>::type>
struct bar <std::vector<X>,
            typename enable_if<
                some_condition<X, Y, Z>
            >::type>
    { ... };

As I worked around, the helper type is used:

template <typename X>
struct bar_enabled {
    typedef typename do_something_with<X>::type Y;
    typedef typename some_other_thing_using<X, Y>::type Z;
    static const bool value = some_condition<X, Y, Z>::value;
};

template <typename X>
struct bar <std::vector<X>,
            typename enable_if_c<
                bar_enabled<X>::value
            >::type>
    { ... };

But for various reasons (among them there is a desire to avoid a separate type, which complicates what I do), I hope that there is a better solution. Any ideas?

+5
1

, :

template <typename X, typename Y, bool>
struct BaseImpl             { /* ... */ };

template <typename X, typename Y>
struct BaseImpl<X, Y, true> { /* ... */ };

template <typename X, typename Y = typename weird_stuff<X>::type>
struct Foo : BaseImpl<X, Y, some_condition<X, Y>::value>
{
    // common stuff
};
+3

All Articles