1,105,332 Community Members

Little advance topic: Lets talk about template

Member Avatar
alwaysLearning0
Junior Poster
119 posts since Apr 2009
Reputation Points: 39 [?]
Q&As Helped to Solve: 19 [?]
Skill Endorsements: 0 [?]
 
0
 

This is just for fun and to see how people do it, it will help me to learn different techniques also.

If no one answers i will understand. :)

Lets say you have a template class. You want a certain method of this class will have some sort of checking mechanism before doing a operation.

Different types of object need different kinds of checking. User of this class know whether he needs to do the check or not. If he needs to do the check then he has to provide a function to this template which template class will call to do the check.

How do you make it generic? for better understanding, below code is to demonstrate what our goal is"

// This is only an example, you can change anything to make it work

template <class T> 
class JustForFun{

    myExecFun(){
         if( /*CHECK THAT Function*/ ){
               sampleExecute();
         } 
         else{
                cout << "condition doesnt match" << endl;
        }
    }

    sampleExecute(){
          //some operation
    }
}
Member Avatar
firstPerson
Industrious Poster
4,052 posts since Dec 2008
Reputation Points: 761 [?]
Q&As Helped to Solve: 634 [?]
Skill Endorsements: 24 [?]
 
0
 

Couple of ways, one way is to do the following :

//interface
struct Conditional{
 virtual bool preCondition()const=0;
 virtual bool postCondition()const=0;
};
//adapter for default
struct ConditionalTrueAdapter: Conditional{
 bool preCondition()const{return true;}
 bool postCondition()const{return true;}
};

//interface
struct Command{
 virtual void execute()=0;
};

class PauseGameCommand : public Command{
private:
 Conditional condition;
public:
 PauseGameCommand(const Conditional& c = ConditionalTrueAdapter())
 : condition(c){}

 void execute(){
   assert(p.preCondition());
   /* code to pause game goes here */
   assert(p.postCondition());
 }
};

Use it like so :

if(user.clickedPauseGame()){   
   PauseGameCommand();
}
else if(user.clickedExitGame()){
  Conditional c = GameState.getGameCondition();
  PauseGameCommand(c); // for example, say, preCondition checks if it can be paused, and postCondition checks if everything went well
}
Member Avatar
mike_2000_17
21st Century Viking
4,063 posts since Jul 2010
Reputation Points: 2,244 [?]
Q&As Helped to Solve: 795 [?]
Skill Endorsements: 71 [?]
Moderator
Featured
Sponsor
 
0
 

@firstPerson: read the question: "let's talk about template" and "How do you make this generic?", this is not a OOP or dynamic polymorphism question, but a question on generic programming and template meta-programming.

Now to answer the (simple) question: this question is essentially generic programming 101. You can make a policy class that implements the checking or the no-checking

struct NoChecking {
  static bool checkCondition(/*..some params..*/) { return true; };
};

template <class T, class CheckingPolicy = NoChecking> 
class JustForFun{

    myExecFun(){
         if( CheckingPolicy::checkCondition(/*..*/) ){
               sampleExecute();
         } 
         else{
                cout << "condition doesnt match" << endl;
        }
    }

    sampleExecute(){
          //some operation
    }
}

Normally, the above should be quite alright. The user can provide its own checking policy class with a static bool method for checking the condition, and/or you can also add a bunch of alternate commonly-used policies of your own. If you are worried about the fact that a conditional evaluated which is always true (when the NoChecking policy is used), don't worry.. the compiler will optimize that away for sure (simple branch reduction).

There are also plenty of alternate solutions in the wonderful world of template meta-programming that would be just as good or better. You can also deal with variable parameters, or what give you.

Member Avatar
firstPerson
Industrious Poster
4,052 posts since Dec 2008
Reputation Points: 761 [?]
Q&As Helped to Solve: 634 [?]
Skill Endorsements: 24 [?]
 
0
 

We'll the situation really didn't call for generic. And to be quite honest, using generic in this situation isn't a good design nor is it flexible.

Member Avatar
alwaysLearning0
Junior Poster
119 posts since Apr 2009
Reputation Points: 39 [?]
Q&As Helped to Solve: 19 [?]
Skill Endorsements: 0 [?]
 
0
 

Thanks both of you for answers.

apologies as my english is not so good, so may be i wasn't clear about the question.

@firstPerson, its not designing question, and I can show lot of examples where you need this kind of generic library class, for instance..

We want to implement a SmartPointer generic class for our use, now we can implement smart pointer in so many different ways. @Mike, now here we can provide the policy classes for different different ways/mechanisms/policy.

In our SmartPointer class we want to provide a way so that user of this class can do certain check before this object get deallocated.

Now lets say there are completely two different kind of object.
one is class MySpecialSocket, this wants to check if the socket has been closed and there are more data to read/write before get deallocating.

another class PausedGame, wants to provide another method to check if the game is still paused, but pointer is getting deleted!!!!

user of SmartPointer may not want to do the check also as his object might not need any check.

template <T>
class SmartPointer
{
        //Smart pointer implementation

        ~SmartPointer{

                if(condition doesn't match)
                        throw "Not Good, we know we shouldn't throw exception from here but still people should know";

         }
}

below is the code of those two class:

class MySpecialSocket{
 //Implementation

 //this is the check method we have to provide to SmartPointer
 bool isSocketStillOpen{
  }
}

code for paused game

class PausedGame{
          //implementaion

//this is the check method we have to provide to SmartPointer
 bool isGameStillPaused{
  }
}

Thanks for taking your valuable time to think about it.

Now how you will solve it? as there are several solutions to this, i know only one, which i am trying to do now..

Member Avatar
mike_2000_17
21st Century Viking
4,063 posts since Jul 2010
Reputation Points: 2,244 [?]
Q&As Helped to Solve: 795 [?]
Skill Endorsements: 71 [?]
Moderator
Featured
Sponsor
 
0
 

Why is the implementation of a deleter policy not totally fine for this situation? Check out how boost smart pointers are implemented for example.

Simply put, I would implement it like this (simplified version of the boost smart pointer implementation):

template <class T>
struct default_deleter {
  void operator()(T* ptr) { delete ptr; };
};

struct null_deleter {
  void operator()(void*) { };
};

template <class T>
struct conditional_deleter {
  typedef bool (T::*condition_function_ptr)();
  condition_function_ptr condition;
  conditional_deleter(condition_function_ptr aFuncPtr) : condition(aFuncPtr) { };
  void operator()(T* ptr) {
    if(!(ptr->*condition)())
      //handle the problem by any other way besides throwing an exception!
    else
      delete ptr;
  };
};
//add a function template for ease:
template <class T>
conditional_deleter<T> make_check(conditional_deleter<T>::condition_function_ptr aFuncPtr) {
  return conditional_deleter<T>(aFuncPtr);
};

template <class T, class DeletePolicy = default_deleter<T> >
class smart_ptr {
  T* ptr; //the stored pointer.
  DeletePolicy deleter; //the deleter object (usually takes 0 memory)
  //..implementation..
  smart_ptr(T* aPtr, DeletePolicy aDeleter) : ptr(aPtr), deleter(aDeleter) { };
  ~smart_ptr() {
    deleter(ptr);
  };
};

class socket {
  //...
  public:
    bool isSocketClosed() {
      //...
    };
};

template <class T>
struct checked_ptr {
  typedef smart_ptr<T, conditional_deleter<T> > type;
};

// instantiate with:
checked_ptr<socket>::type my_ptr(new socket, make_check(&socket::isSocketClosed));

With further manipulations, a reference counting or other schemes can easily be put into this deleter policy. If you want to separate the two policies (checking and deleting) just fuse this solution with the previous one I posted.

On a side note, my opinion is that you don't want to design your classes such that an object is in a state at which it cannot be deleted. Generally, if you follow the RAII idiom, you don't run into these situations. But, as always, there are exceptions (I actually just implemented a class that throws in the deleter! for lack of a better solution, for now..). You can always dump the "dead-but-not-deletable" object in a global garbage collecting thread that checks the condition in a loop and deletes the object when it can.

Member Avatar
alwaysLearning0
Junior Poster
119 posts since Apr 2009
Reputation Points: 39 [?]
Q&As Helped to Solve: 19 [?]
Skill Endorsements: 0 [?]
 
0
 

Thanks mike,

I had similar solution but your one is much more generic and well written.

I am just learning templates advance use. I am just picking up several well known problems/design patterns, and trying to write my own template class to implement those.

I have installed boost and planning to do some code study of boost.

Do you contribute in the boost library?

Regards,

S.

Member Avatar
mike_2000_17
21st Century Viking
4,063 posts since Jul 2010
Reputation Points: 2,244 [?]
Q&As Helped to Solve: 795 [?]
Skill Endorsements: 71 [?]
Moderator
Featured
Sponsor
 
0
 

>>Do you contribute in the boost library?
wow, that's flattering, I wish I did. I think the kind of stuff I program is a bit too specialized (multi-body dynamics, control software and artificial intelligence) for boost which tends to have general use libraries... but who knows, maybe I will someday.

Question Answered as of 3 Years Ago by mike_2000_17 and firstPerson
You
This question has already been solved: Start a new discussion instead
Post:
Start New Discussion
View similar articles that have also been tagged: