Reputation: 4569
I have no idea if the title makes any sense but I can't find the right words to descibe my "problem" in one line. Anyway, here is my problem. There is an interface for a search:
template <typename InputType, typename ResultType> class Search {
public:
virtual void search (InputType) = 0;
virtual void getResult(ResultType&) = 0;
};
and several derived classes like:
template <typename InputType, typename ResultType>
class XMLSearch : public Search<InputType, ResultType> {
public:
void search (InputType) { ... };
void getResult(ResultType&) { ... };
};
The derived classes shall be used in the source code later on. I would like to hold a simple pointer to a Search
without specifying the template parameters, then assign a new XMLSearch and thereby define the template parameters of Search and XMLSearch
Search *s = new XMLSearch<int, int>();
I found a way that works syntactically like what I'm trying to do, but it seems a bit odd to really use it:
template <typename T> class Derived;
class Base {
public:
template <typename T>
bool GetValue(T &value) {
Derived<T> *castedThis=dynamic_cast<Derived<T>* >(this);
if(castedThis)
return castedThis->GetValue(value);
return false;
}
virtual void Dummy() {}
};
template <typename T> class Derived : public Base {
public:
Derived<T>() {
mValue=17;
}
bool GetValue(T &value) {
value=mValue;
return true;
}
T mValue;
};
int main(int argc, char* argv[])
{
Base *v=new Derived<int>;
int i=0;
if(!v->GetValue(i))
std::cout<<"Wrong type int."<<std::endl;
float f=0.0;
if(!v->GetValue(f))
std::cout<<"Wrong type float."<<std::endl;
std::cout<<i<<std::endl<<f;
char c;
std::cin>>c;
return 0;
}
Is there a better way to accomplish this?
Upvotes: 2
Views: 1624
Reputation: 361672
Is there a better way to accomplish this?
Yes, that design is slightly better, since that's using static-dispatching while calling GetValue()
(I'm assuming that dynamic_cast
is typo, you actually wanted to type static_cast
in Base::GetValue()
). In that design, Base::GetValue()
is not virtual, yet it is able to call Derived::GetValue()
using pointer of type Base
. This makes it slightly fast.
But even your way is not that bad. All you've to instantiate your class templates like this:
Search<int,int> *s = new XMLSearch<int, int>();
Your Search *s = new XMLSearch<int, int>()
is wrong!
You can typedef
your templates as follows:
typedef Search<int,int> iisearch;
typedef XMLSearch<int,int> iixmlsearch;
Then use them:
iisearch *s = new iixmlsearch();
This looks better, right?
You can make your class slightly better performance-wise. For that, write your Search class template as follows:
template <typename InputType, typename ResultType> class Search {
public:
void search (InputType input) //it's not virtual anymore!
{
xmlsearch *_this = getXmlSearch();
xmlsearch->search(input);
}
void getResult(ResultType& result) //it's not virtual anymore!
{
xmlsearch *_this = getXmlSearch();
xmlsearch->getResult(result);
}
private:
typedef XMLSearch<InputType, ResultType> xmlsearch;
xmlsearch* getXmlSearch()
{
static xmlsearch *_this= static_cast<xmlsearch* >(this);
return _this;
}
};
Now your base class is not abstract, as it doesn't define virtual functions. This design is slightly faster than your version!
Upvotes: 1