Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

Default template arguments can be used to simulate aliases for complex type expressions in a template declaration. For example:

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 doesn't work. You might ask yourself why a typedef in the body wouldn't work, and the answer is that the aliases need to be in scope before the class body, in order to do conditional enabling; e.g.:

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>
    { ... };

The way I've worked around it is using an auxiliary type:

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 wanting to avoid a separate type, which complicates what I'm doing), I'm hoping that a better solution exists. Any ideas?

For the record, "The template parameter list of a specialization shall not contain default template argument values" [C++11: 14.5.5/8] – Lightness Races in Orbit Mar 15, 2012 at 21:42 @LightnessRacesinOrbit, do you mean to point out that this issue hasn't changed in C++11, or something else? – ajg Mar 15, 2012 at 21:54

Maybe you can stick the distinction into a base class:

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
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.