Reputation: 2413
Template methods as in NOT C++ templates.
So, say that you would like to do some searching with different algorithms - Linear and Binary for instance. And you would also like to run those searches through some common routines so that you could, for instance, automatically record the time that a given search took and so on.
The template method pattern fills the bill beautifully. The only problem is that as far as I've managed to dig around, you can't actually implement this behaviour via static methods with C++, 'cause you would also need to make the methods virtual(?) Which is of course a bit of a bummer because I don't have any need to alter the state of the search object. I would just like to pin all the searching-thingies to its own namespace.
So the question is: Would one want to use something like function/method pointers instead? Or would one just use namespaces to do the job?
It's pretty hard to live with this kind of (dare I say) limitations with C++, as something like this would be a breeze with Java.
Edit:
Oh yeah, and since this is a school assignment, the use of external libraries (other than STL) isn't really an option. Sorry for the hassle.
Upvotes: 0
Views: 5384
Reputation: 247969
I don't see why you'd need the template method pattern.
Why not just define those algorithms as functors that can be passed to your benchmarking function?
struct BinarySearch { // functor implementing a specific search algorithm
template <typename iter_type>
void operator()(iter_type first, iter_type last){ ....}
};
template <typename data_type, typename search_type>
void BenchmarkSearch(data_type& data, search_type search){ // general benchmarking/bookkeeping function
// init timer
search(data);
// compute elapsed time
}
and then call it like this:
int main(){
std::vector<int> vec;
vec.push_back(43);
vec.push_back(2);
vec.push_back(8);
vec.push_back(13);
BenchmarkSearch(vec, BinarySearch());
BenchmarkSearch(vec, LinearSearch()); // assuming more search algorithms are defined
BenchmarkSearch(vec, SomeOtherSearch();
}
Of course, another approach, which is a bit closer to what you initially wanted, could be to use CRTP (A pretty clever pattern for emulating virtual functions at compile-time - and it works with static methods too):
template <typename T>
struct SearchBase { // base class implementing general bookkeeping
static void Search() {
// do general bookkeeping, initialize timers, whatever you need
T::Search(); // Call derived search function
// Wrap up, do whatever bookkeeping is left
}
}
struct LinearSearch : SearchBase<LinearSearch> // derived class implementing the specific search algorithms
{
static void Search(){
// Perform the actual search
}
};
Then you can call the static functions:
SearchBase<LinearSearch>::Search();
SearchBase<BinarySearch>::Search();
SearchBase<SomeOtherSearch>::Search();
As a final note, it might be worth mentioning that both of these approaches should carry zero overhead. Unlike anything involving virtual functions, the compiler is fully aware of which functions are called here, and can and will inline them, resulting in code that is just as efficient as if you'd hand-coded each case.
Upvotes: 5
Reputation: 45345
Here's a simple templatized version that would work
template <typename F, typename C>
clock_t timer(F f, C c)
{
clock_t begin = clock();
f(c);
return clock() - begin;
}
void mySort(std::vector<int> vec)
{ std::sort(vec.begin(), vec.end()); }
int main()
{
std::vector<int> vec;
std::cout << timer(mySort, vec) << std::endl;
return 0;
}
Upvotes: 2
Reputation: 791849
static
doesn't say "I don't need alter an object's state" is says, "I don't need an object". If you need virtual dispatch then you need an object on which to perform virtual dispatch as virtual dispatch is polymorphism based on the runtime type of an object. const
would be "I don't need to alter an object's state" and you can have methods which are virtual
and const
.
Upvotes: 1
Reputation: 36439
You can always implement it the same way you would in Java - pass in an abstract class ISearchable that has a search() method, and override that in LinearSearch and BinarySearch...
You can also use a function pointer (which would be my preffered solution) or a boost::function, or templatize your function and pass in a functor.
Upvotes: 0