How do I get around for not allowing templated virtual function





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







0















How do I work around for not having the support for templated virtual function?



I have a requirement to create a Builder/Command class which can store templated argument which is used later to call methods to do some processing.



Basically builder should be able to store templated values, maybe there is a different(more correct) way of doing it.



After setting all the values, later I want to call an execute method which will use the templated values to call an internal method.



class BuilderImpl {
public:
virtual void execute() = 0;
virtual int type() = 0;
private:
// common properties here
};

template <typename T1, typename T2>
class BuilderImpl2: public BuilderImpl {
public:
BuilderImpl2(const T1 &v1, const T2 &v2) : mVar1{v1}, mVar2{v2} {
}

virtual void execute() override {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}

virtual int type() override {
return 2;
}


T1 mVar1;
T2 mVar2;
};


template <typename T>
class BuilderImpl1: public BuilderImpl {
public:
typedef BuilderImpl1<T> CLAZZ;

BuilderImpl1(const T &v) : mVar1{v} {
}

virtual void execute() override {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}

virtual int type() override {
return 1;
}

template <typename T2>
std::shared_ptr<BuilderImpl> add(const T2 &v2) {
return std::make_shared<BuilderImpl2<T, T2>>(mVar1, v2);
}

T mVar1;
};

class Builder {
public:
void execute() {
std::cout << __FUNCTION__ << std::endl;

if (mImpl) {
mImpl->execute();
}
}

template <typename T>
void add(const T &v) {
if (!mImpl) {
mImpl = std::make_shared<BuilderImpl1<T>>(v);
} else if (mImpl->type() == 1) {
// How do I update my implementation mImpl to point with an instance of BuilderImpl2, any trick?
//mImpl = std::static_pointer_cast<BuilderImpl1<???>>(mImpl)->add(v);
}
}

protected:
std::shared_ptr<BuilderImpl> mImpl{ nullptr };
};

void templatebuilder() {
Builder builder;
builder.add(10);
builder.add(0.0);
builder.execute();
}









share|improve this question


















  • 2





    I am unable to correlate your description with your code. It's unclear to me what you are asking.

    – R Sahu
    Jan 4 at 3:14











  • I don't think this will work, since you don't have access to know which T was used to initialize mImpl when add() is called a 2nd time with a different T. You may need to rethink your design to use fewer templated descendants and use more concrete classes for each T you want to support.

    – Remy Lebeau
    Jan 4 at 4:11




















0















How do I work around for not having the support for templated virtual function?



I have a requirement to create a Builder/Command class which can store templated argument which is used later to call methods to do some processing.



Basically builder should be able to store templated values, maybe there is a different(more correct) way of doing it.



After setting all the values, later I want to call an execute method which will use the templated values to call an internal method.



class BuilderImpl {
public:
virtual void execute() = 0;
virtual int type() = 0;
private:
// common properties here
};

template <typename T1, typename T2>
class BuilderImpl2: public BuilderImpl {
public:
BuilderImpl2(const T1 &v1, const T2 &v2) : mVar1{v1}, mVar2{v2} {
}

virtual void execute() override {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}

virtual int type() override {
return 2;
}


T1 mVar1;
T2 mVar2;
};


template <typename T>
class BuilderImpl1: public BuilderImpl {
public:
typedef BuilderImpl1<T> CLAZZ;

BuilderImpl1(const T &v) : mVar1{v} {
}

virtual void execute() override {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}

virtual int type() override {
return 1;
}

template <typename T2>
std::shared_ptr<BuilderImpl> add(const T2 &v2) {
return std::make_shared<BuilderImpl2<T, T2>>(mVar1, v2);
}

T mVar1;
};

class Builder {
public:
void execute() {
std::cout << __FUNCTION__ << std::endl;

if (mImpl) {
mImpl->execute();
}
}

template <typename T>
void add(const T &v) {
if (!mImpl) {
mImpl = std::make_shared<BuilderImpl1<T>>(v);
} else if (mImpl->type() == 1) {
// How do I update my implementation mImpl to point with an instance of BuilderImpl2, any trick?
//mImpl = std::static_pointer_cast<BuilderImpl1<???>>(mImpl)->add(v);
}
}

protected:
std::shared_ptr<BuilderImpl> mImpl{ nullptr };
};

void templatebuilder() {
Builder builder;
builder.add(10);
builder.add(0.0);
builder.execute();
}









share|improve this question


















  • 2





    I am unable to correlate your description with your code. It's unclear to me what you are asking.

    – R Sahu
    Jan 4 at 3:14











  • I don't think this will work, since you don't have access to know which T was used to initialize mImpl when add() is called a 2nd time with a different T. You may need to rethink your design to use fewer templated descendants and use more concrete classes for each T you want to support.

    – Remy Lebeau
    Jan 4 at 4:11
















0












0








0








How do I work around for not having the support for templated virtual function?



I have a requirement to create a Builder/Command class which can store templated argument which is used later to call methods to do some processing.



Basically builder should be able to store templated values, maybe there is a different(more correct) way of doing it.



After setting all the values, later I want to call an execute method which will use the templated values to call an internal method.



class BuilderImpl {
public:
virtual void execute() = 0;
virtual int type() = 0;
private:
// common properties here
};

template <typename T1, typename T2>
class BuilderImpl2: public BuilderImpl {
public:
BuilderImpl2(const T1 &v1, const T2 &v2) : mVar1{v1}, mVar2{v2} {
}

virtual void execute() override {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}

virtual int type() override {
return 2;
}


T1 mVar1;
T2 mVar2;
};


template <typename T>
class BuilderImpl1: public BuilderImpl {
public:
typedef BuilderImpl1<T> CLAZZ;

BuilderImpl1(const T &v) : mVar1{v} {
}

virtual void execute() override {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}

virtual int type() override {
return 1;
}

template <typename T2>
std::shared_ptr<BuilderImpl> add(const T2 &v2) {
return std::make_shared<BuilderImpl2<T, T2>>(mVar1, v2);
}

T mVar1;
};

class Builder {
public:
void execute() {
std::cout << __FUNCTION__ << std::endl;

if (mImpl) {
mImpl->execute();
}
}

template <typename T>
void add(const T &v) {
if (!mImpl) {
mImpl = std::make_shared<BuilderImpl1<T>>(v);
} else if (mImpl->type() == 1) {
// How do I update my implementation mImpl to point with an instance of BuilderImpl2, any trick?
//mImpl = std::static_pointer_cast<BuilderImpl1<???>>(mImpl)->add(v);
}
}

protected:
std::shared_ptr<BuilderImpl> mImpl{ nullptr };
};

void templatebuilder() {
Builder builder;
builder.add(10);
builder.add(0.0);
builder.execute();
}









share|improve this question














How do I work around for not having the support for templated virtual function?



I have a requirement to create a Builder/Command class which can store templated argument which is used later to call methods to do some processing.



Basically builder should be able to store templated values, maybe there is a different(more correct) way of doing it.



After setting all the values, later I want to call an execute method which will use the templated values to call an internal method.



class BuilderImpl {
public:
virtual void execute() = 0;
virtual int type() = 0;
private:
// common properties here
};

template <typename T1, typename T2>
class BuilderImpl2: public BuilderImpl {
public:
BuilderImpl2(const T1 &v1, const T2 &v2) : mVar1{v1}, mVar2{v2} {
}

virtual void execute() override {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}

virtual int type() override {
return 2;
}


T1 mVar1;
T2 mVar2;
};


template <typename T>
class BuilderImpl1: public BuilderImpl {
public:
typedef BuilderImpl1<T> CLAZZ;

BuilderImpl1(const T &v) : mVar1{v} {
}

virtual void execute() override {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}

virtual int type() override {
return 1;
}

template <typename T2>
std::shared_ptr<BuilderImpl> add(const T2 &v2) {
return std::make_shared<BuilderImpl2<T, T2>>(mVar1, v2);
}

T mVar1;
};

class Builder {
public:
void execute() {
std::cout << __FUNCTION__ << std::endl;

if (mImpl) {
mImpl->execute();
}
}

template <typename T>
void add(const T &v) {
if (!mImpl) {
mImpl = std::make_shared<BuilderImpl1<T>>(v);
} else if (mImpl->type() == 1) {
// How do I update my implementation mImpl to point with an instance of BuilderImpl2, any trick?
//mImpl = std::static_pointer_cast<BuilderImpl1<???>>(mImpl)->add(v);
}
}

protected:
std::shared_ptr<BuilderImpl> mImpl{ nullptr };
};

void templatebuilder() {
Builder builder;
builder.add(10);
builder.add(0.0);
builder.execute();
}






c++ c++11






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Jan 4 at 2:48









RanjithRanjith

206




206








  • 2





    I am unable to correlate your description with your code. It's unclear to me what you are asking.

    – R Sahu
    Jan 4 at 3:14











  • I don't think this will work, since you don't have access to know which T was used to initialize mImpl when add() is called a 2nd time with a different T. You may need to rethink your design to use fewer templated descendants and use more concrete classes for each T you want to support.

    – Remy Lebeau
    Jan 4 at 4:11
















  • 2





    I am unable to correlate your description with your code. It's unclear to me what you are asking.

    – R Sahu
    Jan 4 at 3:14











  • I don't think this will work, since you don't have access to know which T was used to initialize mImpl when add() is called a 2nd time with a different T. You may need to rethink your design to use fewer templated descendants and use more concrete classes for each T you want to support.

    – Remy Lebeau
    Jan 4 at 4:11










2




2





I am unable to correlate your description with your code. It's unclear to me what you are asking.

– R Sahu
Jan 4 at 3:14





I am unable to correlate your description with your code. It's unclear to me what you are asking.

– R Sahu
Jan 4 at 3:14













I don't think this will work, since you don't have access to know which T was used to initialize mImpl when add() is called a 2nd time with a different T. You may need to rethink your design to use fewer templated descendants and use more concrete classes for each T you want to support.

– Remy Lebeau
Jan 4 at 4:11







I don't think this will work, since you don't have access to know which T was used to initialize mImpl when add() is called a 2nd time with a different T. You may need to rethink your design to use fewer templated descendants and use more concrete classes for each T you want to support.

– Remy Lebeau
Jan 4 at 4:11














2 Answers
2






active

oldest

votes


















2














It’s impossible to do this in an automatic, extensible fashion: two translation units could define types A and B, necessitating the construction of an impossible type BuilderImpl2<A,B>. (This is related to the fact that for n input types you need O(n^2) implementations.)



So you have to explicitly list the types you support for at least one side. The most direct way of doing this is with a ladder of dynamic_casts:



if(const auto p=dynamic_cast<BuilderImpl1<A>>(mImpl.get())) mImpl=p->add(v);
else if(const auto p=…) mImpl=p->add(v);
// …
else die_horribly();


(You might add a convenience method to let you write const auto p=mImpl->cast<A>().) There might be a nicer way of indexing with the dynamic type of the BuilderImpl1, but that’s a separate issue.






share|improve this answer































    1














    This is a complement to Davis's answer.



    The line typedef BuilderImpl1<T> CLAZZ; let think that you are used to Java. There is a strong difference between Java and C++ here:




    • Java uses generics with type erasure. There is only one class for any specialization, and simply controls are applied at compile time

    • C++ use templates. There is one different class for every specialization, and that class must be defined at compile time. That is the reason why the implementation of templated classes must be in include files, unless you know all the implementations that will be used and declare them at compile time.






    share|improve this answer
























    • Complement to the complement: one usually uses the injected class name instead of such a typedef.

      – Davis Herring
      Jan 4 at 15:32












    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54032541%2fhow-do-i-get-around-for-not-allowing-templated-virtual-function%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    2














    It’s impossible to do this in an automatic, extensible fashion: two translation units could define types A and B, necessitating the construction of an impossible type BuilderImpl2<A,B>. (This is related to the fact that for n input types you need O(n^2) implementations.)



    So you have to explicitly list the types you support for at least one side. The most direct way of doing this is with a ladder of dynamic_casts:



    if(const auto p=dynamic_cast<BuilderImpl1<A>>(mImpl.get())) mImpl=p->add(v);
    else if(const auto p=…) mImpl=p->add(v);
    // …
    else die_horribly();


    (You might add a convenience method to let you write const auto p=mImpl->cast<A>().) There might be a nicer way of indexing with the dynamic type of the BuilderImpl1, but that’s a separate issue.






    share|improve this answer




























      2














      It’s impossible to do this in an automatic, extensible fashion: two translation units could define types A and B, necessitating the construction of an impossible type BuilderImpl2<A,B>. (This is related to the fact that for n input types you need O(n^2) implementations.)



      So you have to explicitly list the types you support for at least one side. The most direct way of doing this is with a ladder of dynamic_casts:



      if(const auto p=dynamic_cast<BuilderImpl1<A>>(mImpl.get())) mImpl=p->add(v);
      else if(const auto p=…) mImpl=p->add(v);
      // …
      else die_horribly();


      (You might add a convenience method to let you write const auto p=mImpl->cast<A>().) There might be a nicer way of indexing with the dynamic type of the BuilderImpl1, but that’s a separate issue.






      share|improve this answer


























        2












        2








        2







        It’s impossible to do this in an automatic, extensible fashion: two translation units could define types A and B, necessitating the construction of an impossible type BuilderImpl2<A,B>. (This is related to the fact that for n input types you need O(n^2) implementations.)



        So you have to explicitly list the types you support for at least one side. The most direct way of doing this is with a ladder of dynamic_casts:



        if(const auto p=dynamic_cast<BuilderImpl1<A>>(mImpl.get())) mImpl=p->add(v);
        else if(const auto p=…) mImpl=p->add(v);
        // …
        else die_horribly();


        (You might add a convenience method to let you write const auto p=mImpl->cast<A>().) There might be a nicer way of indexing with the dynamic type of the BuilderImpl1, but that’s a separate issue.






        share|improve this answer













        It’s impossible to do this in an automatic, extensible fashion: two translation units could define types A and B, necessitating the construction of an impossible type BuilderImpl2<A,B>. (This is related to the fact that for n input types you need O(n^2) implementations.)



        So you have to explicitly list the types you support for at least one side. The most direct way of doing this is with a ladder of dynamic_casts:



        if(const auto p=dynamic_cast<BuilderImpl1<A>>(mImpl.get())) mImpl=p->add(v);
        else if(const auto p=…) mImpl=p->add(v);
        // …
        else die_horribly();


        (You might add a convenience method to let you write const auto p=mImpl->cast<A>().) There might be a nicer way of indexing with the dynamic type of the BuilderImpl1, but that’s a separate issue.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Jan 4 at 7:50









        Davis HerringDavis Herring

        9,0301736




        9,0301736

























            1














            This is a complement to Davis's answer.



            The line typedef BuilderImpl1<T> CLAZZ; let think that you are used to Java. There is a strong difference between Java and C++ here:




            • Java uses generics with type erasure. There is only one class for any specialization, and simply controls are applied at compile time

            • C++ use templates. There is one different class for every specialization, and that class must be defined at compile time. That is the reason why the implementation of templated classes must be in include files, unless you know all the implementations that will be used and declare them at compile time.






            share|improve this answer
























            • Complement to the complement: one usually uses the injected class name instead of such a typedef.

              – Davis Herring
              Jan 4 at 15:32
















            1














            This is a complement to Davis's answer.



            The line typedef BuilderImpl1<T> CLAZZ; let think that you are used to Java. There is a strong difference between Java and C++ here:




            • Java uses generics with type erasure. There is only one class for any specialization, and simply controls are applied at compile time

            • C++ use templates. There is one different class for every specialization, and that class must be defined at compile time. That is the reason why the implementation of templated classes must be in include files, unless you know all the implementations that will be used and declare them at compile time.






            share|improve this answer
























            • Complement to the complement: one usually uses the injected class name instead of such a typedef.

              – Davis Herring
              Jan 4 at 15:32














            1












            1








            1







            This is a complement to Davis's answer.



            The line typedef BuilderImpl1<T> CLAZZ; let think that you are used to Java. There is a strong difference between Java and C++ here:




            • Java uses generics with type erasure. There is only one class for any specialization, and simply controls are applied at compile time

            • C++ use templates. There is one different class for every specialization, and that class must be defined at compile time. That is the reason why the implementation of templated classes must be in include files, unless you know all the implementations that will be used and declare them at compile time.






            share|improve this answer













            This is a complement to Davis's answer.



            The line typedef BuilderImpl1<T> CLAZZ; let think that you are used to Java. There is a strong difference between Java and C++ here:




            • Java uses generics with type erasure. There is only one class for any specialization, and simply controls are applied at compile time

            • C++ use templates. There is one different class for every specialization, and that class must be defined at compile time. That is the reason why the implementation of templated classes must be in include files, unless you know all the implementations that will be used and declare them at compile time.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Jan 4 at 8:51









            Serge BallestaSerge Ballesta

            81.4k961134




            81.4k961134













            • Complement to the complement: one usually uses the injected class name instead of such a typedef.

              – Davis Herring
              Jan 4 at 15:32



















            • Complement to the complement: one usually uses the injected class name instead of such a typedef.

              – Davis Herring
              Jan 4 at 15:32

















            Complement to the complement: one usually uses the injected class name instead of such a typedef.

            – Davis Herring
            Jan 4 at 15:32





            Complement to the complement: one usually uses the injected class name instead of such a typedef.

            – Davis Herring
            Jan 4 at 15:32


















            draft saved

            draft discarded




















































            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.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54032541%2fhow-do-i-get-around-for-not-allowing-templated-virtual-function%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Monofisismo

            Angular Downloading a file using contenturl with Basic Authentication

            Olmecas