How can I make a class agnostic of its members type?












1














I have a templated class



template <typename T> 
class Templated {
T someValue;
//...
};


and another class with a member of type Templated.



class Holder {
Templated t;
//...
};


This would not compile, because actual type of Holder::Templated is not known. I want Holder::Templated to be initialized / created later, it's value and also type will be read from a configuration file. How can I create Holder objects but add the actual Holder::Templated members later?



I could have a base class to Templated and hold the base class pointer in the Holder class, but I don't like this option. Do you have any other ideas to keep the Holder class agnostic of the type of its Templated member?



Thank you very much!










share|improve this question


















  • 4




    You'll need some kind of type erasure then. If C++17 is an option, you might want to try std::any.
    – lubgr
    Nov 20 at 14:16








  • 1




    You're out of luck. Templates are a compile-time feature. Polymorphism might be a better tool for your job.
    – DeiDei
    Nov 20 at 14:16










  • Thanks @lubgr, C++14 unfortunately. However you gave me a keyword to read about.
    – lulijeta
    Nov 20 at 14:48
















1














I have a templated class



template <typename T> 
class Templated {
T someValue;
//...
};


and another class with a member of type Templated.



class Holder {
Templated t;
//...
};


This would not compile, because actual type of Holder::Templated is not known. I want Holder::Templated to be initialized / created later, it's value and also type will be read from a configuration file. How can I create Holder objects but add the actual Holder::Templated members later?



I could have a base class to Templated and hold the base class pointer in the Holder class, but I don't like this option. Do you have any other ideas to keep the Holder class agnostic of the type of its Templated member?



Thank you very much!










share|improve this question


















  • 4




    You'll need some kind of type erasure then. If C++17 is an option, you might want to try std::any.
    – lubgr
    Nov 20 at 14:16








  • 1




    You're out of luck. Templates are a compile-time feature. Polymorphism might be a better tool for your job.
    – DeiDei
    Nov 20 at 14:16










  • Thanks @lubgr, C++14 unfortunately. However you gave me a keyword to read about.
    – lulijeta
    Nov 20 at 14:48














1












1








1







I have a templated class



template <typename T> 
class Templated {
T someValue;
//...
};


and another class with a member of type Templated.



class Holder {
Templated t;
//...
};


This would not compile, because actual type of Holder::Templated is not known. I want Holder::Templated to be initialized / created later, it's value and also type will be read from a configuration file. How can I create Holder objects but add the actual Holder::Templated members later?



I could have a base class to Templated and hold the base class pointer in the Holder class, but I don't like this option. Do you have any other ideas to keep the Holder class agnostic of the type of its Templated member?



Thank you very much!










share|improve this question













I have a templated class



template <typename T> 
class Templated {
T someValue;
//...
};


and another class with a member of type Templated.



class Holder {
Templated t;
//...
};


This would not compile, because actual type of Holder::Templated is not known. I want Holder::Templated to be initialized / created later, it's value and also type will be read from a configuration file. How can I create Holder objects but add the actual Holder::Templated members later?



I could have a base class to Templated and hold the base class pointer in the Holder class, but I don't like this option. Do you have any other ideas to keep the Holder class agnostic of the type of its Templated member?



Thank you very much!







c++ templates






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 20 at 14:13









lulijeta

419415




419415








  • 4




    You'll need some kind of type erasure then. If C++17 is an option, you might want to try std::any.
    – lubgr
    Nov 20 at 14:16








  • 1




    You're out of luck. Templates are a compile-time feature. Polymorphism might be a better tool for your job.
    – DeiDei
    Nov 20 at 14:16










  • Thanks @lubgr, C++14 unfortunately. However you gave me a keyword to read about.
    – lulijeta
    Nov 20 at 14:48














  • 4




    You'll need some kind of type erasure then. If C++17 is an option, you might want to try std::any.
    – lubgr
    Nov 20 at 14:16








  • 1




    You're out of luck. Templates are a compile-time feature. Polymorphism might be a better tool for your job.
    – DeiDei
    Nov 20 at 14:16










  • Thanks @lubgr, C++14 unfortunately. However you gave me a keyword to read about.
    – lulijeta
    Nov 20 at 14:48








4




4




You'll need some kind of type erasure then. If C++17 is an option, you might want to try std::any.
– lubgr
Nov 20 at 14:16






You'll need some kind of type erasure then. If C++17 is an option, you might want to try std::any.
– lubgr
Nov 20 at 14:16






1




1




You're out of luck. Templates are a compile-time feature. Polymorphism might be a better tool for your job.
– DeiDei
Nov 20 at 14:16




You're out of luck. Templates are a compile-time feature. Polymorphism might be a better tool for your job.
– DeiDei
Nov 20 at 14:16












Thanks @lubgr, C++14 unfortunately. However you gave me a keyword to read about.
– lulijeta
Nov 20 at 14:48




Thanks @lubgr, C++14 unfortunately. However you gave me a keyword to read about.
– lulijeta
Nov 20 at 14:48












3 Answers
3






active

oldest

votes


















2














If you don't want to keep a pointer to templateds base class inside holder, you can add a layer of indirection and have templated itself hold a pointer to its concrete implementation.



class Holder {
Untemplated u;
//...
};

class Untemplated {
//...
struct Templated_base {
//... virtual interface
};
Templated_base* hook; // or better with smart pointers

template <typename T>
struct Templated : Templated_base {
// ... final interface
};

template <typename T>
Untemplated(T&& x) { hook = new Templated<T>(std::forward<T>(x)); }
};


This is only a rough sketch of an elaborate strategy devised by Sean Parent (see this: http://sean-parent.stlab.cc/papers-and-presentations/#better-code-runtime-polymorphism), which allows to use dynamic polymorphism somewhere without paying a price everywhere.






share|improve this answer





















  • Thanks @papagaga, this one looks actually promising.
    – lulijeta
    Nov 20 at 14:48










  • Ah, was it really Sean Parent who devised it? He certainly presents it spectacularly, but devising the technique is quite an attribution.
    – StoryTeller
    Nov 20 at 15:07












  • @StoryTeller: you tell me the story then!
    – papagaga
    Nov 20 at 15:30






  • 1




    @papagaga - You made the claim, so you back it up. That's where burden of proof is, not on me to disprove it.
    – StoryTeller
    Nov 20 at 15:36










  • @StoryTeller: here's my proof: citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.89.1257
    – papagaga
    Nov 20 at 15:53



















0














You can use std::any to hold a value of any type or std::variant to hold values from a set of types. E.g.:



#include <any>

class Holder {
std::any t;
//...
};





share|improve this answer





























    0














    Templates are purely a compile-time polymorphism construct. You need run-time polymorphism, which can be achieved in many different ways in C++:




    • Inheritance + virtual functions: useful when you have an interface and an open set of implementors;


    • std::variant: useful when you have a known closed set of choices;


    • std::any: useful when you want to store any arbitrary object without any restriction


    • More: std::function, dyno, ...







    share|improve this answer





















      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%2f53394928%2fhow-can-i-make-a-class-agnostic-of-its-members-type%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      3 Answers
      3






      active

      oldest

      votes








      3 Answers
      3






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      2














      If you don't want to keep a pointer to templateds base class inside holder, you can add a layer of indirection and have templated itself hold a pointer to its concrete implementation.



      class Holder {
      Untemplated u;
      //...
      };

      class Untemplated {
      //...
      struct Templated_base {
      //... virtual interface
      };
      Templated_base* hook; // or better with smart pointers

      template <typename T>
      struct Templated : Templated_base {
      // ... final interface
      };

      template <typename T>
      Untemplated(T&& x) { hook = new Templated<T>(std::forward<T>(x)); }
      };


      This is only a rough sketch of an elaborate strategy devised by Sean Parent (see this: http://sean-parent.stlab.cc/papers-and-presentations/#better-code-runtime-polymorphism), which allows to use dynamic polymorphism somewhere without paying a price everywhere.






      share|improve this answer





















      • Thanks @papagaga, this one looks actually promising.
        – lulijeta
        Nov 20 at 14:48










      • Ah, was it really Sean Parent who devised it? He certainly presents it spectacularly, but devising the technique is quite an attribution.
        – StoryTeller
        Nov 20 at 15:07












      • @StoryTeller: you tell me the story then!
        – papagaga
        Nov 20 at 15:30






      • 1




        @papagaga - You made the claim, so you back it up. That's where burden of proof is, not on me to disprove it.
        – StoryTeller
        Nov 20 at 15:36










      • @StoryTeller: here's my proof: citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.89.1257
        – papagaga
        Nov 20 at 15:53
















      2














      If you don't want to keep a pointer to templateds base class inside holder, you can add a layer of indirection and have templated itself hold a pointer to its concrete implementation.



      class Holder {
      Untemplated u;
      //...
      };

      class Untemplated {
      //...
      struct Templated_base {
      //... virtual interface
      };
      Templated_base* hook; // or better with smart pointers

      template <typename T>
      struct Templated : Templated_base {
      // ... final interface
      };

      template <typename T>
      Untemplated(T&& x) { hook = new Templated<T>(std::forward<T>(x)); }
      };


      This is only a rough sketch of an elaborate strategy devised by Sean Parent (see this: http://sean-parent.stlab.cc/papers-and-presentations/#better-code-runtime-polymorphism), which allows to use dynamic polymorphism somewhere without paying a price everywhere.






      share|improve this answer





















      • Thanks @papagaga, this one looks actually promising.
        – lulijeta
        Nov 20 at 14:48










      • Ah, was it really Sean Parent who devised it? He certainly presents it spectacularly, but devising the technique is quite an attribution.
        – StoryTeller
        Nov 20 at 15:07












      • @StoryTeller: you tell me the story then!
        – papagaga
        Nov 20 at 15:30






      • 1




        @papagaga - You made the claim, so you back it up. That's where burden of proof is, not on me to disprove it.
        – StoryTeller
        Nov 20 at 15:36










      • @StoryTeller: here's my proof: citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.89.1257
        – papagaga
        Nov 20 at 15:53














      2












      2








      2






      If you don't want to keep a pointer to templateds base class inside holder, you can add a layer of indirection and have templated itself hold a pointer to its concrete implementation.



      class Holder {
      Untemplated u;
      //...
      };

      class Untemplated {
      //...
      struct Templated_base {
      //... virtual interface
      };
      Templated_base* hook; // or better with smart pointers

      template <typename T>
      struct Templated : Templated_base {
      // ... final interface
      };

      template <typename T>
      Untemplated(T&& x) { hook = new Templated<T>(std::forward<T>(x)); }
      };


      This is only a rough sketch of an elaborate strategy devised by Sean Parent (see this: http://sean-parent.stlab.cc/papers-and-presentations/#better-code-runtime-polymorphism), which allows to use dynamic polymorphism somewhere without paying a price everywhere.






      share|improve this answer












      If you don't want to keep a pointer to templateds base class inside holder, you can add a layer of indirection and have templated itself hold a pointer to its concrete implementation.



      class Holder {
      Untemplated u;
      //...
      };

      class Untemplated {
      //...
      struct Templated_base {
      //... virtual interface
      };
      Templated_base* hook; // or better with smart pointers

      template <typename T>
      struct Templated : Templated_base {
      // ... final interface
      };

      template <typename T>
      Untemplated(T&& x) { hook = new Templated<T>(std::forward<T>(x)); }
      };


      This is only a rough sketch of an elaborate strategy devised by Sean Parent (see this: http://sean-parent.stlab.cc/papers-and-presentations/#better-code-runtime-polymorphism), which allows to use dynamic polymorphism somewhere without paying a price everywhere.







      share|improve this answer












      share|improve this answer



      share|improve this answer










      answered Nov 20 at 14:31









      papagaga

      482311




      482311












      • Thanks @papagaga, this one looks actually promising.
        – lulijeta
        Nov 20 at 14:48










      • Ah, was it really Sean Parent who devised it? He certainly presents it spectacularly, but devising the technique is quite an attribution.
        – StoryTeller
        Nov 20 at 15:07












      • @StoryTeller: you tell me the story then!
        – papagaga
        Nov 20 at 15:30






      • 1




        @papagaga - You made the claim, so you back it up. That's where burden of proof is, not on me to disprove it.
        – StoryTeller
        Nov 20 at 15:36










      • @StoryTeller: here's my proof: citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.89.1257
        – papagaga
        Nov 20 at 15:53


















      • Thanks @papagaga, this one looks actually promising.
        – lulijeta
        Nov 20 at 14:48










      • Ah, was it really Sean Parent who devised it? He certainly presents it spectacularly, but devising the technique is quite an attribution.
        – StoryTeller
        Nov 20 at 15:07












      • @StoryTeller: you tell me the story then!
        – papagaga
        Nov 20 at 15:30






      • 1




        @papagaga - You made the claim, so you back it up. That's where burden of proof is, not on me to disprove it.
        – StoryTeller
        Nov 20 at 15:36










      • @StoryTeller: here's my proof: citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.89.1257
        – papagaga
        Nov 20 at 15:53
















      Thanks @papagaga, this one looks actually promising.
      – lulijeta
      Nov 20 at 14:48




      Thanks @papagaga, this one looks actually promising.
      – lulijeta
      Nov 20 at 14:48












      Ah, was it really Sean Parent who devised it? He certainly presents it spectacularly, but devising the technique is quite an attribution.
      – StoryTeller
      Nov 20 at 15:07






      Ah, was it really Sean Parent who devised it? He certainly presents it spectacularly, but devising the technique is quite an attribution.
      – StoryTeller
      Nov 20 at 15:07














      @StoryTeller: you tell me the story then!
      – papagaga
      Nov 20 at 15:30




      @StoryTeller: you tell me the story then!
      – papagaga
      Nov 20 at 15:30




      1




      1




      @papagaga - You made the claim, so you back it up. That's where burden of proof is, not on me to disprove it.
      – StoryTeller
      Nov 20 at 15:36




      @papagaga - You made the claim, so you back it up. That's where burden of proof is, not on me to disprove it.
      – StoryTeller
      Nov 20 at 15:36












      @StoryTeller: here's my proof: citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.89.1257
      – papagaga
      Nov 20 at 15:53




      @StoryTeller: here's my proof: citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.89.1257
      – papagaga
      Nov 20 at 15:53













      0














      You can use std::any to hold a value of any type or std::variant to hold values from a set of types. E.g.:



      #include <any>

      class Holder {
      std::any t;
      //...
      };





      share|improve this answer


























        0














        You can use std::any to hold a value of any type or std::variant to hold values from a set of types. E.g.:



        #include <any>

        class Holder {
        std::any t;
        //...
        };





        share|improve this answer
























          0












          0








          0






          You can use std::any to hold a value of any type or std::variant to hold values from a set of types. E.g.:



          #include <any>

          class Holder {
          std::any t;
          //...
          };





          share|improve this answer












          You can use std::any to hold a value of any type or std::variant to hold values from a set of types. E.g.:



          #include <any>

          class Holder {
          std::any t;
          //...
          };






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 20 at 14:19









          Maxim Egorushkin

          85.1k1199181




          85.1k1199181























              0














              Templates are purely a compile-time polymorphism construct. You need run-time polymorphism, which can be achieved in many different ways in C++:




              • Inheritance + virtual functions: useful when you have an interface and an open set of implementors;


              • std::variant: useful when you have a known closed set of choices;


              • std::any: useful when you want to store any arbitrary object without any restriction


              • More: std::function, dyno, ...







              share|improve this answer


























                0














                Templates are purely a compile-time polymorphism construct. You need run-time polymorphism, which can be achieved in many different ways in C++:




                • Inheritance + virtual functions: useful when you have an interface and an open set of implementors;


                • std::variant: useful when you have a known closed set of choices;


                • std::any: useful when you want to store any arbitrary object without any restriction


                • More: std::function, dyno, ...







                share|improve this answer
























                  0












                  0








                  0






                  Templates are purely a compile-time polymorphism construct. You need run-time polymorphism, which can be achieved in many different ways in C++:




                  • Inheritance + virtual functions: useful when you have an interface and an open set of implementors;


                  • std::variant: useful when you have a known closed set of choices;


                  • std::any: useful when you want to store any arbitrary object without any restriction


                  • More: std::function, dyno, ...







                  share|improve this answer












                  Templates are purely a compile-time polymorphism construct. You need run-time polymorphism, which can be achieved in many different ways in C++:




                  • Inheritance + virtual functions: useful when you have an interface and an open set of implementors;


                  • std::variant: useful when you have a known closed set of choices;


                  • std::any: useful when you want to store any arbitrary object without any restriction


                  • More: std::function, dyno, ...








                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 20 at 14:19









                  Vittorio Romeo

                  56.9k17152292




                  56.9k17152292






























                      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.





                      Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                      Please pay close attention to the following guidance:


                      • 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%2f53394928%2fhow-can-i-make-a-class-agnostic-of-its-members-type%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

                      Ottavio Pratesi

                      Tricia Helfer

                      15 giugno