I've written a method which automatically interpolates an expensive 2D function in C++. I'm now trying to allow the class to accept a function pointer so that any function can be interpolated. To do this, it appears I need a templated class so that I can template it for each object which it needs to evaluate the function pointer upon. That part is not so bad after I realized I need to define the class entirely in the header so that the linker can template out the class for each object needed. Now the rub.
Within the class I use boost::unordered_map to store function evaluations so that I don't unnecessarily call the function. During the interpolation I refine a grid so that it sufficiently describes it (based upon its curvature). I'm locally subdividing the mesh, so that if my original points were at x=0, .5, 1, the next set might be x=0, .25, .5, 1, where I would only need to evaluate at x = .25 for the second pass. That's working on its own with a hard coded function, in place of the dynamic function pointer.
The trouble I am having is in defining the necessary operator and hash_value functions for the boost::tuple. If I put it in the header they are defined multiple times (for each include of the header). If I try and compile it as an object and link it in, the linker fails to find the definitions. The two definitions I need to reference in the class:
bool operator==(const BoostTuple2D &a, const BoostTuple2D &b)
{
return a.tuple.get<0>() == b.tuple.get<0>() &&
a.tuple.get<1>() == b.tuple.get<1>();
}
std::size_t hash_value(const BoostTuple2D &e)
{
std::size_t seed = 0;
boost::hash_combine(seed, e.tuple.get<0>());
boost::hash_combine(seed, e.tuple.get<1>());
return seed;
}
In my header I have a struct and typedef:
struct BoostTuple2D {
BoostTuple2D(double x1, double x2)
: tuple(x1, x2) {}
boost::tuples::tuple<double, double> tuple;
};
typedef boost::unordered_map< BoostTuple2D, double > BoostTuple2DMap;
Which is just above my templated class, with ommitions:
template<class F>
class Interpolate {
public:
class Evaluate {
// this class uses the map to cache evaluations of the dynamic pointer
}
Interpolate (double (F::*f)(double, double), F & obj, [...]) : f(f), object(obj), ... {};
private:
// members
};
How can I make the operator== and hash_value methods available to the class without defining them multiple times? I am guarding the header file. I am a c++ newbee, so hopefully its something simple I'm not getting. Thanks!
In the case of non-template methods in a header, you will need to preceed them with the keyword 'inline'. While there is no guarantee that the function will be inlined (it is merely a hint in this case), it does require the linker allow multiple definitions.
If you're having problem placing them in their own source file, but leaving the declaration in the hedaer, there might be an issue with the namespace you're putting them in. I would have to see that version of the code to help.
As a note, tuples should already have an
operator==
defined, so you can use that instead of comparing element by element yourself (the default already does that).