Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to simulate default template arguments in partial specializations?

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?

like image 715
ajg Avatar asked Mar 15 '12 21:03

ajg


People also ask

Can we specify default value for template arguments?

You cannot give default arguments to the same template parameters in different declarations in the same scope. The compiler will not allow the following example: template<class T = char> class X; template<class T = char> class X { };

What is mean by template specialization?

The act of creating a new definition of a function, class, or member of a class from a template declaration and one or more template arguments is called template instantiation. The definition created from a template instantiation is called a specialization.

What are template arguments?

In C++ this can be achieved using template parameters. A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.


1 Answers

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
};
like image 72
Kerrek SB Avatar answered Sep 22 '22 17:09

Kerrek SB