Gabriel Grigoras
Gabriel Grigoras

Reputation: 151

Template template parameters used as default value for other arguments

I'm trying to use a template template parameter as a default value for other template parameters but when I try to use the identifier (template template parameter name/id ) it cannot be found. I'm using VS 2013. The idea is that I have a "factory" class based on a specific type of template instantiation I need to return another object with the same number of parameters (4) BUT with the same specialization.

template<class T1, class T2,class T3, class T4>
class CommandBus
{...}

template <
template<class T1, class T2, class T3, class T4> class ListenerType,
//The Line bellow fails to compile, T1 is not visible
//E0020 identifier "T1" is undefine 
class CommandBusType = CommandBus<T1, T2, T3, T4> >
class CommandBusFactory {
static auto Get() {
        return CommandBusType{};
    }
};

int main{
//Say I would Have some Object :
Listener<int, int ,int int> Listener;
//Withought the Factory I would have to manually generate a ComamndBus of the same specialization (int , int , int, int):
CommandBus<int,int,int,int> cmdBus;


//But I could use a factory, things should look like:
Listener<int, int ,int int> listener;
auto cmdBus = CommandBusFactory<Listener<int,int,int,int>>::Get();
}

I was expecting this to work but the compiler complains that for example identifier T1,T2 etc not found for the default value (CommandBus)for template parameter CommandBusType.

Is is possible to use template template arguments as default value for other template arguments?

Upvotes: 1

Views: 255

Answers (2)

Fire Lancer
Fire Lancer

Reputation: 30135

It is not entirely clear what you are attempting here. The use of the template there will allow CommandBusFactory to create different instantiations of the provided ListenerType, rather than for them to be passed in, e.g.:

template <
    template<class T1, class T2, class T3, class T4> class ListenerType,
    class CommandBusType
>
class CommandBusFactory {
    static auto Get() {
        ListenerType<int, int, float, float> listener; // template params go here
        ListenerType<std::string, std::string, double, double> listener2; // allowing different ones
        return CommandBusType{};
    }
};
int main() {
    CommandBusFactory<Listener, SomeCommandBus> factory; // not here
}

If you do want to provide the ListenerType up front, and then determine CommandBusType from that, you might use typedefs, return values, or similar means (like containers having value_type, etc.).

template<class T1, class T2, class T3, class T4> class CommandBus {};
template<class T1, class T2, class T3, class T4> class Listener
{
public:
    typedef T1 t1;
    typedef T2 t2;
    typedef T3 t3;
    typedef T4 t4;
};
template <
    class ListenerType,
    class CommandBusType = CommandBus<typename ListenerType::t1, typename ListenerType::t2, typename ListenerType::t3, typename ListenerType::t4>
>
class CommandBusFactory {
    static auto Get() {
        return CommandBusType{};
    }
};

int main() {
    CommandBusFactory<Listener<int,int,float,float>> factory;
}

Upvotes: 1

HolyBlackCat
HolyBlackCat

Reputation: 96236

The first template paramater of CommandBusFactory is itself a template.

And yet, in main you pass Listener<int,int,int,int> to it, which is not a template, but a type. You need a type template parameter instead.

Then, to extract template arguments from that type you could use template specialization:

template
<
    class X,
    template <class, class, class, class> class Y
>
struct copy_template_params;

template
<
    template <class, class, class, class> class X,
    class A, class B, class C, class D,
    template <class, class, class, class> class Y
>
struct copy_template_params<X<A,B,C,D>,Y>
{
    using type = Y<A,B,C,D>;
};

template
<
    class ListenerType, 
    class CommandBusType = typename copy_template_params<ListenerType,CommandBus>::type
>
class CommandBusFactory
{
  public:
    static auto Get()
    {
        return CommandBusType{};
    }
};

Upvotes: 2

Related Questions