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.
inline 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;
}
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).