Mihai
Mihai

Reputation: 1084

Reduce template parameters tightly linked to each other

I have the following code:

template<typename T1, typename T2, typename T3, typename T4>
void Func(void); // signature

Simple template function with 4 template parameters. The usage of this is currently like this:

Func<Foo1, Foo1Helper, Foo1Client, Foo1Server>();
Func<Foo2, Foo2Helper, Foo2Client, Foo2Server>();
Func<Foo3, Foo3Helper, Foo3Client, Foo3Server>();

Now in the usage examples, Foo1Helper, Foo1Client, Foo1Server, Foo2Helper, Foo2Client, Foo2Server, Foo3Helper, Foo3Client, Foo3Server are generated classes based on the Foo1, Foo2, Foo3 classes.

What i want to achieve is to simplify the Func templated function so that it can be called like this:

Func<Foo1>();

without needing so specify also the generated classes since the name of the classes is bounded to the original class.

Do you have any suggestions on how i can achieve this?

Upvotes: 1

Views: 41

Answers (3)

Guillaume Racicot
Guillaume Racicot

Reputation: 41770

You could group Foo related class like that:

struct FooProfile {
    using T = Foo1;
    using Helper = Foo1Helper;
    using Client = Foo1Client;
    using Server = Foo1Server;
};

And pass it like that:

Func<FooProfile>();

The function implementation would look like that:

template<typename Profile>
void Func() {
    using T = typename Profile::T;
    using Helper = typename Profile::Helper;
    using Client = typename Profile::Client;
    using Server = typename Profile::Server;

    // stuff
}

Upvotes: 2

NathanOliver
NathanOliver

Reputation: 180510

Another option is to use a macro. The syntax is a little different but you could have something like

#define PARAMS(name) name, name##Helper, name##Client, name##Server

And then you would use it like

Func<PARAMS(Foo1)>();

Upvotes: 2

lisyarus
lisyarus

Reputation: 15522

It is not entirely clear what does generated classes mean, but you can provide a metafunction for them:

// declare metafunctions
template <typename T>
struct Helper;

template <typename T>
struct Client;

template <typename T>
struct Server;

// provide implementations
template <>
struct Helper<Foo1>
{ using type = Foo1Helper; };

template <>
struct Client<Foo1>
{ using type = Foo1Client; };

template <>
struct Server<Foo1>
{ using type = Foo1Server; };

// the same for Foo2, Foo3, etc

and then use them in Func:

template <typename T>
void Func()
{
    using THelper = typename Helper<T>::type;
    using TClient = typename Client<T>::type;
    using TServer = typename Server<T>::type;
}

Upvotes: 4

Related Questions