Kheldar
Kheldar

Reputation: 53

Templates with different parameters

I can't find a way to turn the following templates into only one with the same effect. My goal is to instanciate a subclass of a Form. Subclasses can have constructors with none to two parameters.

template<class T> bool Session::OpenForm() {
    Form* form = new T();
    return OpenForm(form);
}

template<class T, class U> bool Session::OpenForm(U parameter) {
    Form* form = new T(parameter);
    return OpenForm(form);
}

template<class T, class U, class V> bool Session::OpenForm(U parameter1, V parameter2) {
    Form* form = new T(parameter1, parameter2);
    return OpenForm(form);
}

I use those templates like this :

session->OpenForm<SubForm>();
session->OpenForm<OtherSubForm>("Title");

Looking around i thought using optional parameters could do the trick but i can't make it working. I tried things like this :

template<class T, class U = T, class V = T> 
bool Session::OpenForm(U parameter1 = NULL, V parameter2 = NULL) {
    Form* form = NULL;

    if(parameter2 != NULL) form = new T(parameter1, parameter2);
    else if(parameter1 != NULL) form = new T(parameter1);
    else form = new T();
}

Is there a way to have only one template to take care of that ? Or maybe just a better way ?

I use C++03.

Thanks

Upvotes: 2

Views: 89

Answers (1)

AndyG
AndyG

Reputation: 41090

I'm going to technically answer your question, but not solve the crux of it --- what you really want is variadic templates, which is a C++11 feature.

Instead, you can put all the work on the implementor of each additional SubForm type: each new SubForm class must have a constructor that accepts an args struct that the SubForm can use to initialize itself.

For example:

struct SubFormArgs{};
struct OtherSubFormArgs{
    OtherSubFormArgs(std::string s) : param1(s){}
    std::string param1;
};

struct Form{};

struct SubForm : Form{
    SubForm(SubFormArgs){}
};

struct OtherSubForm : Form{
    OtherSubForm(OtherSubFormArgs args): myStr(args.param1){}
    std::string myStr;
}

SubForm uses SubFormArgs to construct itself, and OtherSubForm uses OtherSubFormArgs to construct itself.

This simplifies your OpenForm function like so:

bool OpenForm(Form* f){/*...*/}

struct Session
{
    template<class T, class U>
    bool OpenForm(U ctor_params)
    {
        Form* form = new T(ctor_params);
        return ::OpenForm(form);
    }
};

And a test:

Session* session = new Session();
session->OpenForm<SubForm>(SubFormArgs());
session->OpenForm<OtherSubForm>(OtherSubFormArgs("Title"));

Demo

Upvotes: 1

Related Questions