I just decided to get a bit more acustomed to using templates. Maybe this is a stupid question, but in my experience in C++ there is always some pitfall lurking aroung the corner. Thus I prefer the danger of embarresment instead of building up on bad habbits. Mainly as an exercise I wrote this:
#include <functional>
#include <string>
#include <sstream>
template <typename V,template <class> class R = std::greater,typename I=void>
struct Extremum {
typedef V value_type;
typedef I index_type;
typedef R<V> relation_type;
V value;
I index;
R<V> r;
bool operator() (V v,I i){
bool result = r(v,value);
if (result){
value = v;
index = i;
}
return result;
}
Extremum(V v,I i) : value(v),index(i) {}
std::string toString(){
std::stringstream s;
s << "value= " << value << " index= " << index;
return s.str();
}
};
template <typename V,template <class> class R>
struct Extremum<V,R,void> {
typedef V value_type;
typedef void index_type;
typedef R<V> realtion_type;
V value;
R<V> r;
bool operator() (V v){
bool result = r(v,value);
if (result){ value = v; }
return result;
}
Extremum(V v) : value(v) {}
std::string toString(){
std::stringstream s;
s << "value= " << value;
return s.str();
}
};
which would be used like this:
Extremum<int,std::greater,int > e(0,0);
e(10,3);
e(123,5);
std::cout << e.toString() << std::endl;
Extremum<int> g(0);
g(123);
g(1234);
g(1);
std::cout << g.toString() << std::endl;
I used a ´toString()´ because it is for debugging and printing to the screen while I might want to overload in/output operators for real in/output.
I dont like so much the ordering of the template parameters, as both the second and the third parameter would make a good fit as the last parameter so it can be ommited on the instantiation. However, I guess there is no better solution than simply choosing one ordering.
I have no idea how to provide good initial values. My idea was to use something like std::numeric_limits<V>::max
, however, it depends too much on the choosen relation whether it should be max
, min
or something completely different. Maybe the easiest is let the user choose them when calling the constructor.
Aside from its functionaliy, which probably could be achieved with less code and a simple lambda or the like, is there anything inherently broken with this code? Anything obvious that could be improved?
Note that this is pre-C++11, but I would also be interested in any post-C++11 stuff.