static polymorphism and Factory Pattern

Discussion in 'C++' started by alexander.stippler@uni-ulm.de, Jul 26, 2006.

  1. Guest

    Hello,

    I need on the one hand static polymorphism for efficiency concerns,
    e.g.

    template <typename P>
    class Problem
    {
    public:
    const P &
    problem() const { return static_cast<const P &>(*this); }

    P &
    problem() { return static_cast<P &>(*this); }

    void
    method1() { this->problem().method1(); }

    // .... other methods
    };

    template <typename T>
    class SpecificProblem
    : public Problem<SpecificProblem<T> >
    {
    public:
    void
    method1() {}
    };

    There is one specific interface all derived classes have to share, so
    this CRTP-method is well suited.
    But I also want the following: Which specific problem I have to
    instantiate is given by some external run-time value, let's say by a
    string. Ok, so I could use the Factory pattern for instatiation. But
    for this pattern I need some common base class as return type for the
    created object. Let us for the moment consider we have this type
    'ProblemType *' (it cannot be 'Problem *'!). There is no way back such
    that I could use the structure above, i.e. call 'method1()' efficiently
    (or at all). Any solutions.
    I need:
    several classes all sharing a common interface.
    a method like factory pattern to instantiate the classes given a
    'string value'
    efficient usage of the class's methods afterwards (no virtual
    function calls!)
    I fear, that's too many requirements to fulfill at the same time.

    Best regards,
    Alex
     
    , Jul 26, 2006
    #1
    1. Advertising

  2. wrote:
    > I need:
    > several classes all sharing a common interface.
    > a method like factory pattern to instantiate the classes given a
    > 'string value'
    > efficient usage of the class's methods afterwards (no virtual
    > function calls!)
    > I fear, that's too many requirements to fulfill at the same time.


    Why can you not make a virtual function call?

    Josh McFarlane
     
    Josh Mcfarlane, Jul 26, 2006
    #2
    1. Advertising

  3. Guest

    Josh Mcfarlane schrieb:

    > wrote:
    > > I need:
    > > several classes all sharing a common interface.
    > > a method like factory pattern to instantiate the classes given a
    > > 'string value'
    > > efficient usage of the class's methods afterwards (no virtual
    > > function calls!)
    > > I fear, that's too many requirements to fulfill at the same time.

    >
    > Why can you not make a virtual function call?
    >
    > Josh McFarlane


    because the functions are very simple, called thousands of times and
    the virtual function overhead would be performance critical.
     
    , Jul 26, 2006
    #3
  4. BigBrian Guest

    wrote:
    > because the functions are very simple, called thousands of times and
    > the virtual function overhead would be performance critical.


    It seems most people who make this claim do so on their belief and not
    on fact. Have you tested your statement by actual measurement?

    Usually, if you eliminate the polymorphism, you will end up with a
    switch statement in your code. For efficiency, both are about the
    same. But using virtual functions will produce code that is cleaner
    and easier to maintain and extend.

    -Brian
     
    BigBrian, Jul 26, 2006
    #4
  5. Arne Adams Guest

    <> schrieb im Newsbeitrag
    news:...
    > Hello,
    >
    > I need on the one hand static polymorphism for efficiency concerns,
    > But I also want the following: Which specific problem I have to
    > instantiate is given by some external run-time value, let's say by a
    > string.


    If you could put the creation and the handling of the problem into 1
    function it could be done like this:
    (But it is no longer evident what the Baseclass Problem<T> is for)

    #include <map>
    #include <string>


    template <typename P>
    class Problem
    {
    public:
    const P &
    problem() const { return static_cast<const P &>(*this); }

    P &
    problem() { return static_cast<P &>(*this); }

    void
    method1() { this->problem().method1(); }

    // .... other methods
    };

    template <typename T>
    class SpecificProblem
    : public Problem<SpecificProblem<T> >
    {
    public:
    void method1() {}
    };

    typedef void (*CreateAndSolveFunction)();

    template<typename P> void Solve(Problem<P>& trouble)
    {
    trouble.method1();
    }

    template<typename ConcreteTrouble> void DoCreateAndSolve()
    {
    SpecificProblem<ConcreteTrouble> concreteTrouble;
    Solve(concreteTrouble);
    }

    typedef std::map<std::string, CreateAndSolveFunction> SolvableProblems;

    SolvableProblems InitSolvableProblems()
    {
    SolvableProblems result;
    result[std::string("int")]=&DoCreateAndSolve<int>;
    return result;
    }

    void CreateAndSolve(std::string const& problemId)
    {
    static const SolvableProblems solvableProblems = InitSolvableProblems();
    SolvableProblems::const_iterator where =
    solvableProblems.find(problemId);
    if(where != solvableProblems.end())
    (*where->second)();
    }

    int main()
    {
    CreateAndSolve("int");
    }

    Regards,
    Arne
     
    Arne Adams, Jul 26, 2006
    #5
  6. Guest

    BigBrian schrieb:

    > wrote:
    > > because the functions are very simple, called thousands of times and
    > > the virtual function overhead would be performance critical.

    >
    > It seems most people who make this claim do so on their belief and not
    > on fact. Have you tested your statement by actual measurement?
    >


    Yes. I have.

    > Usually, if you eliminate the polymorphism, you will end up with a
    > switch statement in your code. For efficiency, both are about the
    > same. But using virtual functions will produce code that is cleaner
    > and easier to maintain and extend.
    >
    > -Brian


    I do not see how my polymorphism problem can be mapped to switch
    statements. You mean a switch depending on the type? If yes, what does
    this have to do with my problem?
     
    , Jul 26, 2006
    #6
  7. Guest

    Arne Adams schrieb:

    > <> schrieb im Newsbeitrag
    > news:...
    > > Hello,
    > >
    > > I need on the one hand static polymorphism for efficiency concerns,
    > > But I also want the following: Which specific problem I have to
    > > instantiate is given by some external run-time value, let's say by a
    > > string.

    >
    > If you could put the creation and the handling of the problem into 1
    > function it could be done like this:
    > (But it is no longer evident what the Baseclass Problem<T> is for)
    >
    > #include <map>
    > #include <string>
    >
    >
    > template <typename P>
    > class Problem
    > {
    > public:
    > const P &
    > problem() const { return static_cast<const P &>(*this); }
    >
    > P &
    > problem() { return static_cast<P &>(*this); }
    >
    > void
    > method1() { this->problem().method1(); }
    >
    > // .... other methods
    > };
    >
    > template <typename T>
    > class SpecificProblem
    > : public Problem<SpecificProblem<T> >
    > {
    > public:
    > void method1() {}
    > };
    >
    > typedef void (*CreateAndSolveFunction)();
    >
    > template<typename P> void Solve(Problem<P>& trouble)
    > {
    > trouble.method1();
    > }
    >
    > template<typename ConcreteTrouble> void DoCreateAndSolve()
    > {
    > SpecificProblem<ConcreteTrouble> concreteTrouble;
    > Solve(concreteTrouble);
    > }
    >
    > typedef std::map<std::string, CreateAndSolveFunction> SolvableProblems;
    >
    > SolvableProblems InitSolvableProblems()
    > {
    > SolvableProblems result;
    > result[std::string("int")]=&DoCreateAndSolve<int>;
    > return result;
    > }
    >
    > void CreateAndSolve(std::string const& problemId)
    > {
    > static const SolvableProblems solvableProblems = InitSolvableProblems();
    > SolvableProblems::const_iterator where =
    > solvableProblems.find(problemId);
    > if(where != solvableProblems.end())
    > (*where->second)();
    > }
    >
    > int main()
    > {
    > CreateAndSolve("int");
    > }
    >
    > Regards,
    > Arne


    Thanks for your idea. You never have to deal with the concrete
    Problem's type at all. Clever. But unfortunately this is not enough in
    my situation. I have to be able to pass the ConcreteProblem to
    functions as argument. I just considered if virtual functions are
    really that evil to my problem, test it and they are!! So I perhaps
    have to think about completely different approaches.

    Alex
     
    , Jul 27, 2006
    #7
  8. Arne Adams Guest

    Hi,


    <> schrieb im Newsbeitrag
    news:...
    >
    > Arne Adams schrieb:
    >
    >> template<typename P> void Solve(Problem<P>& trouble)
    >> {
    >> trouble.method1();
    >> }
    >>
    >> template<typename ConcreteTrouble> void DoCreateAndSolve()
    >> {
    >> SpecificProblem<ConcreteTrouble> concreteTrouble;
    >> Solve(concreteTrouble);
    >> }
    >>

    >
    > Thanks for your idea. You never have to deal with the concrete
    > Problem's type at all. Clever. But unfortunately this is not enough in
    > my situation. I have to be able to pass the ConcreteProblem to
    > functions as argument.


    Could you post code for what you need to do?

    Note that Solve could as well operate directly on the most derived problem
    type because Solve is called in a context where that type is statically
    known.

    Arne
     
    Arne Adams, Jul 27, 2006
    #8
  9. Guest

    Arne Adams schrieb:

    > Hi,
    >
    >
    > <> schrieb im Newsbeitrag
    > news:...
    > >
    > > Arne Adams schrieb:
    > >
    > >> template<typename P> void Solve(Problem<P>& trouble)
    > >> {
    > >> trouble.method1();
    > >> }
    > >>
    > >> template<typename ConcreteTrouble> void DoCreateAndSolve()
    > >> {
    > >> SpecificProblem<ConcreteTrouble> concreteTrouble;
    > >> Solve(concreteTrouble);
    > >> }
    > >>

    > >
    > > Thanks for your idea. You never have to deal with the concrete
    > > Problem's type at all. Clever. But unfortunately this is not enough in
    > > my situation. I have to be able to pass the ConcreteProblem to
    > > functions as argument.

    >
    > Could you post code for what you need to do?
    >
    > Note that Solve could as well operate directly on the most derived problem
    > type because Solve is called in a context where that type is statically
    > known.
    >
    > Arne


    OK. I think code wold be too lengthy. The concept:
    - a library providing mainly a special kind of 'Solver'. As input it
    needs some
    'Problem' given by a) a descrition file (several parameters)
    and b) a realization of a class
    'SpecificProblem' implementing some methods
    which are to be called by the Solver
    instantiation and are
    problem specific (very frequently
    called).
    - which specific realization of Problem shoud be used is given by a
    string in the description file.
    - the main 'Solver' class should be able to pass its argument - the
    SpecificProblem - to other
    parts implementing the Solver ingredients.

    I tend to think, that the CRTP is the thing one could perhaps replace.
    The need for efficient function calls for the SpecificProblem is
    perhaps easier to fulfill than the combination of CRTP and Factory
    methods. Keeping the factory approach one then has to find a way for
    efficient realizations of SpecificProblem.

    Alex
     
    , Jul 27, 2006
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Medi Montaseri
    Replies:
    17
    Views:
    920
    Medi Montaseri
    Sep 3, 2003
  2. Krivenok Dmitry
    Replies:
    13
    Views:
    1,495
    Axter
    Jun 1, 2006
  3. sunny
    Replies:
    1
    Views:
    482
    Salt_Peter
    Dec 7, 2006
  4. Markus Dehmann
    Replies:
    2
    Views:
    493
    James Kanze
    Jan 4, 2008
  5. C#
    Replies:
    4
    Views:
    440
Loading...

Share This Page